TypeScript學習筆記

一、數據類型

ts的數據類型幾乎與js一致 提供了數字(number)、字符串(string)、結構體(Object)、布爾值等基礎數據類型,另外還提供了枚舉類(enum)

數字(number)

和js中的一樣ts中的數字都是浮點型 除了支持十進制和十六進制的字面量 ts還支持了 es2015 中引入的二進制和八進制表示形式

let hex:number = 0xf00d;//十六進制
let bin:number = 0b1010;//二進制
let oct:number = 0o744;//八進制```

## 字符串(string) 

與js的string一致 可以使用雙引號( " ) 單引號( ' ) 反引號( ` ) 皆可表示字符串 

```let who: string = "我";// "雙引號 
let name: string = '王鋼蛋';// '單引號
let str: string = `${who}是${name}`;// `模板字符串 
console.log(str); //輸出  我是王鋼蛋

數組(Array)

ts 的數組和js的數組略有不同 ,ts中有兩種形式可以定義數組

第一種

是在數據類型后面跟上[] 表示有此類型的元素組成的一個數組 這點跟java類似

let arr: string[] = ["蔡徐坤","謝廣坤","王鋼蛋","吳電鰻"];

第二種

方式是使用數組Array的泛型

//在以上兩種形式聲明的數組中所有元素必須都是同一類型 那么如何定義一個可以包含不同類型的 數組呢
let arr2: Array<string | number> = [1,"one"]; //數組元素可以是 string型 亦可為 number型
let arr3: Array<any> = [1,"yes",true,{attr:'ok'}]; //any表示任意類型 ```

## 元組(Tuple)

元組表示一個已知長度和各元素類型的數組,各個元素類型可不相同

比如

```let t1: [number,string]
t1 = [1,"one"];//正常賦值
t1 = ["one",1];//報錯 元素類型與聲明時不一致
t1 = [1,"one",3];//報錯  元組長度不對

枚舉(enum)

ts的enum和java的enum基本一致,使用枚舉類型可以為一組數值賦予友好的名字

let green:Color.Green;
console.log(green);// 輸出 #00FF00

任意值(any)

有時候在編程階段不知道一個變量值的類型,這個值的可能來自于動態內容 這種情況下 我們不希望類型檢查器對這些值進行檢查 而是直接讓它們通過編譯,其實就跟js中直接let一個變量效果是一樣的 該變量可以有任意類型的值

a = "four";
a = true;
a = {}
//以上代碼皆可運行

Null 和 Undefined

ts中 undefined和null有自己各自的類型 分別叫做 undefined 和 null 和void相似 他們本身的類型用處不大

默認情況下 null和undefined是所有類型的子類型 也就是說 你可以把null和undefined 賦值給任何類型的變量

let b:string;
let c:number;
a = null;
b = undefined;
c = undefined;```

## 空值(void)

void類型與any類型正好相反 它表示沒有任何類型 一般用在聲明函數返回值時  如果一個函數沒有返回值 則其返回值類型為void 

```function fun():void{
    console.log(`Hello Wolrd!`)
}```

聲明一個void型變量沒有多大意義 因為你只能賦予 `undefined` 和 `null` 

```let a:void = undefined;```

## Nerver 

nerver類型表示那些永遠不存在值的類型 這個類型花里胡哨的 不想看

## Object

`object`表示非原始類型,也就是除`number`,`string`,`boolean`,`symbol`,`null`或`undefined`之外的類型。

使用`object`類型,就可以更好的表示像`Object.create`這樣的API。例如:

```declare function create(o: object | null): void;
create({ prop: 0 }); // OK
create(null); // OK
create(42); // Error
create("string"); // Error
create(false); // Error
create(undefined); // Error```

# 二、變量聲明

這章沒什么好看的 就是一些 var let const 以及其各種作用域問題 跳過

# 三、接口(interface)

ts的核心原則之一就對值所具有的結構進行檢查 它有時被稱作"鴨式辯型法" 或 "結構性子類型化" 在TS中 接口的作用就是為這些類型命名和你的代碼定義契約

## 鴨式辯型法

第一次聽到這個名字 表情是這樣的  ![image.png](https://upload-images.jianshu.io/upload_images/4622762-04ed15f706451062.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "image.png")  其實理解起來非常簡單,鴨式辯型來自一句名言

> 像鴨子一樣走路并且嘎嘎叫的就叫鴨子 ---------------魯迅

![image.png](https://upload-images.jianshu.io/upload_images/4622762-73b3f83b9df844b7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "image.png") 

舉個栗子

```interface Duck {
    name:string,
    age:3  
}
function printDuck(d:Duck){
    console.log(`打印鴨子:`, d);
}
let obj = {name:"可達鴨",age:18};
printDuck(obj)

上面例子中 變量obj擁有了 Duck的所有屬性 那么obj就是一只鴨子 這就是傳說中的"鴨式辯型"

fine 下面開始正式了解interface

image.png

初步了解

好下面來再
image.png

觀察下接口是如何工作的

//打印人類
function printHuman(human:{name:string,age:number,sex:boolean}){
    console.log(`打印人類`,human)
}
let ladyboy = {name: '蔡徐坤', age:38, sex:true,hobby:'唱調 rap 籃球 Music'};
printHuman(ladyboy)

在上面代碼中 類型檢查器會查看 printHuman的調用,printHuman有一個參數,并要求這個對象參數name age sex三個屬性,需要注意的是 我們傳入的對象參數實際上包含很多屬性 但編譯器只會檢查那些必須的屬性書否存在,并且其類型是否匹配,然而 有些時候TS卻不會這么寬松 我們下面會繼續學習

接下在用interface重寫上面的例子

//定義人類
interface Human{
    name:string,
  age:number,
  sex:boolean,  
}
//打印人類
function printHuman(human:Human){
    console.log(`打印人類`,human)
}
let ladyboy = {name: '蔡徐坤', age:38, sex:true,hobby:'唱調 rap 籃球 Music'};
printHuman(ladyboy)

Human 接口就好比一個名字,用來描述上面例子里的需求,他代表了有 name age sex 屬性 且定一個了各自類型的對象 需要注意的是 我們這里不能像在其他語言里一樣說 傳給 printHuman() 的對象實現了這個接口,TS只會去關注值的外形,只要傳入的對象滿足上面提到的條件,那么它就是被允許的,還有要注意的就是 類型檢查器不會去檢查屬性的順序 只要相應的屬性存在并且類型正確即可

可選屬性

接口里的屬性不是全都必需的 有些是只在某些條件下存在或者根本不粗在 可選屬性在應用 ``options bags` 模式很常用 ,即給函數傳入的參數對象中只有部分屬性賦值了

國際慣例
image
//定義人類
interface Human{
    name:string,
  age:number,
  sex:boolean,
  hobby?:string  
}
//打印人類
function printHuman(human:Human){
    console.log(`打印人類`,human)
}
let ladyboy = {name: '蔡徐坤', age:38, sex:true,hobby:'唱調 rap 籃球 Music'};
printHuman(ladyboy)

在上面例子中可以看出 可選屬性和普通接口的定義差不多,只是在可選屬性名字定義后面加一個 問號?

可選屬性的好處之一就是可以對可能存在的屬性進行預定義 好處之二是可以捕獲引用了不存在的屬性時的錯誤比如我們故意將printHuman中的 hobby拼錯誤 就會得到一個錯誤提示

image.png

只讀屬性

一些對象屬性只能在對象剛剛創建的時候修改其值 你可以在屬性名前加 readonly 來指定只讀屬性

//定義人類
interface Human{
    name:string,
    age:number,
    readonly sex:string,
    hobby?:string,
}
let ladyboy:Human = {name: '蔡徐坤', age:38, sex:'girl',hobby:'唱調 rap 籃球 Music'};
ladyboy.age = 48 //正常執行
ladyboy.sex ='boy'//報錯

上面代碼中 ladyboy的sex在創建后將無法改變 否則會出現如下報錯

image.png

只讀數組

TS具有只讀數組 ReadonlyArray<T> 類型 ``Array<T>相似,它只是把所有的可變方法去掉了 如push` 之類的會改變數組元素的方法 因此可以確保數組創建后不能被修改

let a: number[] = [1,2,3,4];
let b:ReadonlyArray<number> = a;
b[0] = 2; //出錯
b.push(5);//出錯
let c:number[] = b;//出錯 不可以將ReadonlyArray<T> 直接復制給 Array<T>
let d:number[] = <number[]> b;//可以通過類型斷言重寫賦值
console.log(`調試:`,a);

readonly VS const

const 定義只讀變量 readonly定義只讀屬性

額外屬性檢查

    name: string,//姓名
    age?:number//年齡
}
function createWoman(woman:Woman):Woman{
    return   woman
}
let cxk:Woman = {name:'蔡徐坤',jjsize:'18cm'};//報錯 
let cxk2 = createWoman( {name:'蔡徐坤',jjsize:'18cm'})//報錯

上面代碼會出現如下報錯 因為interface Woman 沒jjsize屬性
image.png

TS會認為這段代碼可能存在bug 對象字面量會被特殊對待且經過額外的屬性檢查,當他們賦值給變量或作為參數傳遞的時候 如果一個對象的字面量存在任何 '目標類型' 不包含的屬性時 你會得到一個錯誤

想要繞開這些檢查非常簡單 主要有以下三種方法

方法一:類型斷言

let cxk:Woman = {name:'蔡徐坤',jjsize:'18cm'} as Woman;

方法二:索引簽名

索引簽名是最佳的方式 ,前提是你能夠確定這個對象可能具有某些為特殊用途的額外屬性 如果 Woman 帶有上面定義類型的 nameage 屬性 ,并且還帶有任意數量和其他屬性,那么我們可以這樣定義它

interface  Woman {
    name: string,//姓名
    age?:number,//年齡
    [propName :string]:any //任意數量任意類型的其他屬性
}

后面會繼續深入學習索引簽名

方法三:變量賦值

interface  Woman {
    name: string,//姓名
    age?:number,//年齡
}
let human = {name:'蔡徐坤',jjsize:'18cm'};
let cxk:Woman = human

這個方法就是將這個對象復制給另變量 huamn 因為 huamn 不會經過額外屬性檢查所以編譯器不會報錯(這里我是看不大懂 憑什么就不經過額外屬性檢查了

image

這里需要注意的是 huamnWoman 必須要存在共同屬性時才能使用

像下方這樣寫是會報錯的

let human = {jjsize:'18cm'};

let cxk:Woman = human;

函數類型

接口能描述js中各種對象擁有的各樣外形,除了描述帶有屬性的對象外,接口也可以描述函數類型 為了使用接口表示函數類型 我們需要給接口定義一個調用簽名 (就是定義參數列表和返回值類型)

image
//定義一個方法 Todo 接收 時間 地點 人物 事件 四個參數
interface Todo {
    (time:string,where:string,who:string,something:string):boolean
}
let playBasketball:Todo
playBasketball=function(time:string,where:string,who:string,something:string):boolean{
    console.log(`Todo:${who}于${time}在${where}${something}`)
    return true;
}
playBasketball("清明節","孫笑川墳頭","蔡徐坤","打籃球");
//輸出結果 Todo:蔡徐坤于清明節在孫笑川墳頭打籃球

對于函數的類型檢查來說 函數名不需要與接口里定義的一致,函數的參數會進行逐個檢查 要求對應位置上的參數類型是兼容的 如果你不想指定類型 TS的類型系統會推斷出參數類型

可索引的類型

可索引類型具有一個索引簽名,它描述了對象索引的類型 還有相應索引返回值的類型

interface  Woman {
    name: string,//姓名
    age?:number,//年齡
}
//女團
interface WomansArray {
    [index: number]:Woman;
}
//定義女團變量
let womensTeam: WomansArray;

womensTeam = [
    {name:'蔡徐坤'},
    {name:'鹿晗'},
    {name:'張大大'}
]
//單飛的女團成員
let singleWoman:Woman = womensTeam[0];
let singleWoman2:Woman = womensTeam['1']; //字符串與number一致

上面的例子里 我們定義了 WomanArray 接口 它具有索引簽名,這個索引簽名表示了當用 string 去索引WomanArray 時或得到 Woman 類型的返回值

TS支持兩種索引簽名:字符串和數字。可以同時保持兩種類型的索引 但是數字索引的返回值必須是字符串索引返回值的子類型(這句真?繞),這是因為當使用 number 索引時 JS會將它轉換成 string 然后再去索引對象 也就是說用 number 100 去索引等同于用 string "100" 去索引 因此 兩者需要保持一致

(這一塊還是看不大懂 有空再看)

Class類型

與C#或Java里的基本作用一樣TS也能夠用它來明確的強制一個類去符合某種契約

//動物
interface Animal {
    name?:string; //名字 動物不一定都有名字 所以用了可選屬性
    eat(food: string):void   //描述一個eat(吃) 方法  任何動物都需要進食
}
// Huamn (人類) 實現 Animal 接口
class Huamn implements Animal {
    name:string; //名字
    sex:string;  //性別
    age:number;  //年齡
    //構造函數
    constructor(name:string,sex:string,age:number){
        this.name = name;
        this.sex = sex;
        this.age =age;

    }
    //實現接口中的eat()
    eat(food:string){
        console.log(`${this.age}歲的${this.name}${this.sex}士正在吃${food}`) 
    }
}
let  cxk:Huamn = new Huamn("蔡徐坤","女",38)
cxk.eat("籃球");//輸出結果 ..... 38歲的蔡徐坤女士正在吃籃球

你可以在接口中描述一個方法,在類里實現它 如同上例中的 setTime 方法一樣,接口描述了類的公共部分 ,而不是公共和私有兩部分 它不會幫你檢查類是否具有私有成員

類靜態部分與實例部分的區別

類具有兩個類型:靜態部分的類型和實例的類型,當用構造器 constructor 簽名去定義一個接口并試圖定義一個類去實現這個接口時會得到一個錯誤 ,這是因為一個類實現了一個接口時,只對其實力部分進行了類型檢查 ``constructor` 屬于類的靜態部分所以不在檢查范圍內,因此我們應該直接操作類的靜態部分

(這一塊太花里胡哨了 遲點再看)

接口繼承

和類一樣 接口也可以相互繼承,這讓我們能夠從一個接口里復制成員到另一個接口里,可以靈活地接口分割到可重用的模塊里

//動物
interface Animal {
    name?:string; //名字 動物不一定都有名字 所以用了可選屬性
    eat(food: string):void   //描述一個eat(吃) 方法  任何動物都需要進食
}
// Huamn (人類) 實現 Animal 接口
interface Huamn extends Animal {
    name:string; //名字
    sex:string;  //性別
    age:number;  //年齡
}
class Japanese implements Huamn{
    name:string; //名字
    sex:string;  //性別
    age:number;  //年齡
    Country:string = "日本";
    constructor(name:string,sex:string,age:number){
        this.name = name
        this.sex = sex
        this.age = age
    }
    eat(food: string): void {
        console.log(`來自${this.Country}${this.age}歲的${this.name}${this.sex}士正在吃${food}`)
    }
}
let  cxk:Japanese = new Japanese("蔡徐坤","女",38)
cxk.eat("籃球"); //輸出  來自日本38歲的蔡徐坤女士正在吃籃球

一個接口可以繼承多個接口 創建出多個接口合成的接口
image
//動物
interface Animal {
    name?: string; //名字 動物不一定都有名字 所以用了可選屬性
    eat(food: string): void   //描述一個eat(吃) 方法  任何動物都需要進食
}
// Huamn (人類) 實現 Animal 接口
interface Huamn extends Animal {
    name: string; //名字
    sex: string;  //性別
    age: number;  //年齡
}
//明星
 interface  Star {
    fans: number//粉絲數
    opus: string[] //代表作

}
//假明星  繼承了   Human和Star 兩個接口
interface FakeStar extends Huamn,Star{
    buyFakeFans(num:number) //制造假粉絲
    sendLawyersLetter(who:string)//發律師函
}

class StupidStar implements FakeStar{
    public name:string;
    public sex:string;
    public fans:number;
    public opus:string[]=[];
    public age:number;
    constructor(name,sex,age,fans){
        this.name = name
        this.sex = sex
        this.age = age
        this.fans =fans
    }
    //添加作品
    public addOpus(name:string){
        this.opus.push(name)
    }
    public eat(food: string): void {
        console.log(`粉絲量有${this.fans / 10000 }萬,今年${this.age}歲,代表作有${JSON.stringify(this.opus)}的${this.name}${this.sex}士正在吃${food}`)
    }
    public buyFakeFans(num: number) {
        console.log(`粉絲量有${this.fans / 10000 }萬,今年${this.age}歲,代表作有${JSON.stringify(this.opus)}的${this.name}${this.sex}士成功給自己買了${num/10000}萬個假粉絲,`)
        this.fans += num
    }
    public sendLawyersLetter(who: string) {
        console.log(`粉絲量有${this.fans / 10000 }萬,今年${this.age}歲,代表作有${JSON.stringify(this.opus)}的${this.name}${this.sex}士給${who}發了一封律師函`)
    }
}
let cxk: StupidStar = new StupidStar("蔡徐坤", "女", "38",10000000)
cxk.buyFakeFans(100000); //打印輸出  粉絲量有1000萬,今年38歲,代表作有[]的蔡徐坤女士成功給自己買了10萬個假粉絲
cxk.eat("籃球"); //打印輸出 粉絲量有1010萬,今年38歲,代表作有[]的蔡徐坤女士正在吃籃球
cxk.addOpus("《雞你太美》") //添加作品
cxk.sendLawyersLetter("BiliBili");//粉絲量有1010萬,今年38歲,代表作有["《雞你太美》"]的蔡徐坤女士給BiliBili發了一封律師函

混合類型

這個感覺沒什么用 看不明白 有空再看。下面是原文

先前我們提過,接口能夠描述JavaScript里豐富的類型。 因為JavaScript其動態靈活的特點,有時你會希望一個對象可以同時具有上面提到的多種類型。

一個例子就是,一個對象可以同時做為函數和對象使用,并帶有額外的屬性。

interface Counter {
    (start: number): string;
    interval: number;
    reset(): void;
}
function getCounter(): Counter {
    let counter = <Counter>function (start: number): string { return '' };
    counter.interval = 123;
    counter.reset = function () { };
    return counter;
}
let c = getCounter();
c(10);
c.reset();
c.interval = 5.0;

在使用JavaScript第三方庫的時候,你可能需要像上面那樣去完整地定義類型。

接口繼承類

這是什么騷操作??
image.png

當接口繼承哼了一個Class類型時 它會繼承Class的成員 但不包括其實現,就好像接口聲明了類中所有存在的成員但并沒有提供具體實現 ,接口同樣會繼承Class的 private` 和protected` 這意味整合當你創建一個接口繼承了一個擁有私有保護的成員類時 這個接口類型只能被這個類或其子類所實現 當項目中有一個龐大的繼承結構時這很有用 但要注意的是代碼只在子類擁有特定屬性時起作用 除了繼承自基類 子類之間不必相關聯

    private state: any;
}
interface SelectableControl extends Control {
    select(): void;
}
class Button extends Control implements SelectableControl {
    select() { }
}
class TextBox extends Control {
    select() { }
}
// Error: Property 'state' is missing in type 'Image'.
class Image implements SelectableControl {
    select() { }
}
class Location {
}

在上面的例子里,SelectableControl包含了Control的所有成員,包括私有成員state。 因為state是私有成員,所以只能夠是Control的子類們才能實現SelectableControl接口。 因為只有Control的子類才能夠擁有一個聲明于Control的私有成員state,這對私有成員的兼容性是必需的。

Control類內部,是允許通過SelectableControl的實例來訪問私有成員state的。 實際上,SelectableControl就像Control一樣,并擁有一個select方法。 ButtonTextBox類是SelectableControl的子類(因為它們都繼承自Control并有select方法),但ImageLocation類并不是這樣的

四、類(Class)

基本說明就不說了 跟Java一毛一樣

繼承

TS中我們可以使用常用的面向對象模式,基于類的程序設計中一種最基本的模式是允許使用繼承來拓展現有的類

class Animal {//動物
    move(distanceInMeters: number = 0) { //移動方法
        console.log(`Animal moved ${distanceInMeters}m.`);
    }
}
class Dog extends Animal {//狗
    bark() { //叫
        console.log('Woof! Woof!');
    }
}
const dog = new Dog();//實例化
dog.bark();
dog.move(10);
dog.bark();

super關鍵字

在子類中 super 指向父類的this 實際應用見下例

class Animal{
    name:string
    constructor(name:string){
        this.name = name
    }
    eat(food:string){
        console.log(`${this.name}正在吃${food}`)
    }
}
class Human extends Animal{
    constructor(name:string) {
        super(name);
    }
    eating(food:string){
        super.eat(food)
    }
}
let cxk = new Human("蔡徐坤");
cxk.eating("??")

類成員修飾符

類成員共有以下幾種修飾符

public

TS中成員默認都為public 也可以明確的將一個成員標記為 public

class Animal {
    public name: string;
    public constructor(theName: string) { this.name = theName; }
    public move(distanceInMeters: number) {
        console.log(`${this.name} 移動了 ${distanceInMeters}米.`);
    }
}

private

當成員被標記為 private 時 它就不能在類的外部訪問

class Animal {
    private name: string;
    constructor(theName: string) { this.name = theName; }
}

new Animal("Cat").name; // 錯誤: 'name' 是私有的.

protected

readonly

學習中....

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,156評論 6 529
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 97,866評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 174,880評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,398評論 1 308
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,202評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,743評論 1 320
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,822評論 3 438
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 41,962評論 0 285
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,476評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,444評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,579評論 1 365
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,129評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,840評論 3 344
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,231評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,487評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,177評論 3 388
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,568評論 2 370

推薦閱讀更多精彩內容