用VSCode寫(xiě)TypeScript:類(lèi)袍嬉、繼承掩驱、封裝、接口以及模塊

目前前端發(fā)展得百花齊放冬竟、技術(shù)日新月異欧穴,就連各種編輯器也好用到匪夷所思,又層出不窮泵殴。近兩年來(lái)涮帘,我從Sublime Text,到Atom笑诅,到Brackets调缨,再到今天的VSCode疮鲫。從一開(kāi)始不斷玩各種插件配置軟件,到現(xiàn)在幾乎不怎么配置插件就能滿(mǎn)足到我的基本需求弦叶,編輯器軟件之間的競(jìng)爭(zhēng)也甚是激烈俊犯。

VSCode全稱(chēng)是Visual Studio Code, 是一款免費(fèi)開(kāi)源的現(xiàn)代化輕量級(jí)代碼編輯器伤哺,內(nèi)置JavaScript燕侠、TypeScript,支持 Node.js立莉、ES6绢彤、AngularJS、ReactJS等蜓耻,幾乎所有主流的開(kāi)發(fā)語(yǔ)言的語(yǔ)法高亮茫舶、智能代碼補(bǔ)全、自定義熱鍵刹淌、括號(hào)匹配饶氏、代碼片段、代碼對(duì)比 Diff有勾、GIT 等特性疹启,而且擁有豐富的插件生態(tài)系統(tǒng),可通過(guò)安裝插件來(lái)支持C++柠衅、C#、Python籍琳、PHP等其他語(yǔ)言菲宴,并針對(duì)網(wǎng)頁(yè)開(kāi)發(fā)和云端應(yīng)用開(kāi)發(fā)做了優(yōu)化∏骷保跨平臺(tái)支持Windows喝峦,OS X和Linux。運(yùn)行速度非常流暢呜达,不亞于Sublime Text谣蠢,打開(kāi)大文件甚至更有優(yōu)勢(shì)。VSCode和Atom查近、Brackets一樣眉踱,都屬于是Webkit類(lèi)的編輯器。

輕量級(jí)霜威、開(kāi)源谈喳、跨平臺(tái),聽(tīng)起來(lái)就不像是微軟能做出來(lái)的事戈泼。但猶如能生產(chǎn)出TypeScript一樣婿禽,現(xiàn)代的微軟也正在做很現(xiàn)代的事情赏僧,實(shí)在令人刮目相看。

由C#的首席架構(gòu)師安德斯·海爾斯伯格領(lǐng)銜開(kāi)發(fā)的TypeScript扭倾,是JavaScript的一個(gè)超集淀零,向JavaScript添加了可選的靜態(tài)類(lèi)型,強(qiáng)類(lèi)型膛壹,以及模塊系統(tǒng)和基于類(lèi)的面向?qū)ο缶幊碳葜小ypeScript是為大型應(yīng)用之開(kāi)發(fā)而設(shè)計(jì),而編譯時(shí)它產(chǎn)生 JavaScript 以確保兼容性恢筝。

按我的理解是哀卫,微軟希望你學(xué)會(huì)了C#以后,前端撬槽、后端此改、數(shù)據(jù)庫(kù)全部都能編寫(xiě)程序。

首先侄柔,我們先來(lái)了解一下在vscode如何安裝共啃、配置TypeScript。Visual Studio2015和Visual Studio 2013 Update 2默認(rèn)包含了TypeScript暂题。如果你沒(méi)有安裝包含TypeScript的Visual Studio 移剪,可以通過(guò)NPM進(jìn)行安裝:

npm install -g typescript

安裝完成以后,就可以在vscode中編寫(xiě)以及匯編ts文件了薪者。在vscode中匯編只需要在ts文件下纵苛,按著按shift+ctrl+b,會(huì)提示沒(méi)有配置文件言津,點(diǎn)擊配置后會(huì)自動(dòng)在根目錄生成一個(gè).vscode文件夾攻人,里面有個(gè)tasks.json文件,按默認(rèn)配置就可以悬槽。

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "0.1.0",
    "command": "tsc",
    "isShellCommand": true,
    "args": ["-p", "."],
    "showOutput": "silent",
    "problemMatcher": "$tsc"
}

接著在根目錄里面怀吻,新建一個(gè)tsconfig.json的生成配置文件。

{
 "compilerOptions": {
  "target": "ES5",
  "noImplicitAny": false,
  "module": "amd",
  "removeComments": false,
  "sourceMap": true
 }
}

以上初婆,配置ts文件已經(jīng)完成蓬坡。下面我們來(lái)建一個(gè)新類(lèi):class Duck

class Duck {
    DuckName: string;
    Age: number;
    Fly: string;
    constructor(duckName: string, age: number, fly: string) {
        this.DuckName = duckName;
        this.Age = age;
        this.Fly = fly;
    }
    greet() {
        let outString: string = "我是鴨子,我的名字是" + this.DuckName + "磅叛,我現(xiàn)在" + this.Age + "歲," + this.Fly;
        console.log(outString);
    }
}
var getduck = new Duck("黃鴨子", 1, "我會(huì)飛");
getduck.greet();//我是鴨子屑咳,我的名字是黃鴨子,我現(xiàn)在1歲,我會(huì)飛

接著我們遇到一個(gè)客戶(hù)弊琴,他要求把橡皮鴨也要加入我們的系統(tǒng)當(dāng)中乔宿。第一反應(yīng)就是,好吧访雪,我做一個(gè)繼承類(lèi)详瑞。

class Duck {
    DuckName: string;
    Age: number;
    Fly: string;
    constructor(duckName: string, age: number, fly: string) {
        this.DuckName = duckName;
        this.Age = age;
        this.Fly = fly;
    }
    greet() {
        let outString: string = "我是鴨子掂林,我的名字是" + this.DuckName + ",我現(xiàn)在" + this.Age + "歲," + this.Fly;
        console.log(outString);
    }
}

class RubberDuck extends Duck {
    constructor(duckName: string, age: number, fly: string) {
        super(duckName, age, fly);
    }
    greet() {
        let outString: string = "我是橡皮鴨子坝橡,我的名字是" + this.DuckName + "泻帮,我現(xiàn)在" + this.Age + "歲," + this.Fly;
        console.log(outString);
    }
   
}
var getduck = new Duck("黃鴨子", 1, "我會(huì)飛");
var getrubberduck: Duck = new RubberDuck("小鴨子", 0, "我不會(huì)飛");
getduck.greet();//我是鴨子,我的名字是黃鴨子计寇,我現(xiàn)在1歲,我會(huì)飛
getrubberduck.greet();//我是橡皮鴨子锣杂,我的名字是小鴨子,我現(xiàn)在0歲,我不會(huì)飛

其實(shí)我們也可以使用get/set封裝番宁,而不用繼承元莫,就可以達(dá)到上面的目的。

class Duck {
    DuckName: string;
    Age: number;
    Fly: string;
    private _className: string;
    constructor(duckName: string, age: number, fly: string) {
        this.DuckName = duckName;
        this.Age = age;
        this.Fly = fly;
    }

    get className(): string {
        return this._className;
    }

    set className(newname: string) {
        this._className = newname;
        let outString: string = "我是" + newname + "蝶押,我的名字是" + this.DuckName + "踱蠢,我現(xiàn)在" + this.Age + "歲," + this.Fly;
        console.log(outString);
    }

}


var getduck = new Duck("黃鴨子", 1, "我會(huì)飛");
getduck.className = "鴨子"; //我是鴨子,我的名字是黃鴨子棋电,我現(xiàn)在1歲,我會(huì)飛
var getduck = new Duck("小黃", 0, "我不會(huì)飛");
getduck.className = "橡皮鴨子"; //我是橡皮鴨子茎截,我的名字是小黃,我現(xiàn)在0歲,我不會(huì)飛

其實(shí)繼承類(lèi)的目的是在于繼承的同時(shí)進(jìn)行功能的擴(kuò)展赶盔。下面我們除了將鴨子的類(lèi)名加進(jìn)來(lái)企锌,還增加多一個(gè)rubbergreet()的方法:

class Duck {
    DuckName: string;
    Age: number;
    Fly: string;
    constructor(duckName: string, age: number, fly: string) {
        this.DuckName = duckName;
        this.Age = age;
        this.Fly = fly;
    }
    greet() {
        let outString: string = "我是鴨子,我的名字是" + this.DuckName + "于未,我現(xiàn)在" + this.Age + "歲," + this.Fly;
        console.log(outString);
    }
}

class getDuck extends Duck {
    private classname:string;
    constructor(duckName: string, age: number, fly: string,classname:string) {
        super(duckName, age, fly);
        this.classname=classname;
    }
    greet() {
        let outString: string = "我是"+this.classname+"撕攒,我的名字是" + this.DuckName + ",我現(xiàn)在" + this.Age + "歲," + this.Fly;
        console.log(outString);
    }

    rubbergreet(){
        console.log("zzz,zzz");
    }
   
}
var getduck = new Duck("黃鴨子", 1, "我會(huì)飛");
var getrubberduck= new getDuck("小鴨子", 0, "我不會(huì)飛","橡皮鴨子");

getduck.greet();//我是鴨子烘浦,我的名字是黃鴨子抖坪,我現(xiàn)在1歲,我會(huì)飛
getrubberduck.greet();//我是橡皮鴨子,我的名字是小鴨子谎倔,我現(xiàn)在0歲,我不會(huì)飛
getrubberduck.rubbergreet();//zzz,zzz

在類(lèi)名前加上abstract 說(shuō)明這個(gè)類(lèi)是抽象類(lèi),抽象類(lèi)只需要寫(xiě)出類(lèi)的定義,由實(shí)現(xiàn)類(lèi)完成它的具體細(xì)節(jié).

如果去實(shí)體化一個(gè)抽象類(lèi)柳击,將會(huì)產(chǎn)生一個(gè)錯(cuò)誤猿推。不信片习,你拿上面的Duck類(lèi)試試。

假設(shè)由于我們經(jīng)營(yíng)得當(dāng)蹬叭,系統(tǒng)需要升級(jí)藕咏。新來(lái)的工程師看了我們的代碼,叫了一聲:搞什么嘛秽五,這完全可以用接口孽查!

什么是接口呢?類(lèi)是對(duì)象的抽象坦喘,那么接口就是類(lèi)的抽象盲再。有一個(gè)編程原則是這樣子說(shuō)的:針對(duì)接口編程西设,而不是針對(duì)現(xiàn)實(shí)編程。

下面我們寫(xiě)一個(gè)簡(jiǎn)單的接口答朋,把鴨子的類(lèi)和接口先組合贷揽。

interface DuckConfig {
  DuckName?: string;
  Age?: number;
  Fly?: string;
  Duckclass?: string;
}

function createDuck(config:DuckConfig):{out:string;}
{
    var newDuck={out:"我是"};
    if (config.Duckclass){
        newDuck.out+=config.Duckclass;
    }
    else{
        newDuck.out+="鴨子";
    }
    if (config.DuckName){
        newDuck.out+=",我的名字是"+config.DuckName;
    }
    if (config.Age){
        newDuck.out+="梦碗,我今年"+config.Age+"歲";
    }
    if (config.Fly){
        newDuck.out+="禽绪,"+config.Fly;
    }
    console.log(newDuck.out);
    return newDuck;

}
var blackDuck = createDuck({DuckName:"小黑",Age:1,Fly:"我會(huì)飛",Duckclass: "黑鴨子"});//我是黑鴨子,我的名字是小黑洪规,我今年1歲印屁,我會(huì)飛
var blackDuck = createDuck({DuckName:"小黃",Age:1,Fly:"我不會(huì)飛"});//我是鴨子,我的名字是小黃斩例,我今年1歲雄人,我不會(huì)飛
var rubberDuck = createDuck({Duckclass: "橡皮鴨子"});//我是橡皮鴨子

這樣寫(xiě)挺規(guī)范的,這樣一來(lái)樱拴,我們來(lái)多少種鴨子都不怕了柠衍。我想看看js是怎么處理“接口”的,一看卻傻眼了:

function createDuck(config) {
    var newDuck = { out: "我是" };
    if (config.Duckclass) {
        newDuck.out += config.Duckclass;
    }
    else {
        newDuck.out += "鴨子";
    }
    if (config.DuckName) {
        newDuck.out += "晶乔,我的名字是" + config.DuckName;
    }
    if (config.Age) {
        newDuck.out += "珍坊,我今年" + config.Age + "歲";
    }
    if (config.Fly) {
        newDuck.out += "," + config.Fly;
    }
    console.log(newDuck.out);
    return newDuck;
}
var blackDuck = createDuck({ DuckName: "小黑", Age: 1, Fly: "我會(huì)飛", Duckclass: "黑鴨子" });
var blackDuck = createDuck({ DuckName: "小黃", Age: 1, Fly: "我不會(huì)飛" });
var rubberDuck = createDuck({ Duckclass: "橡皮鴨子" });

config就是一個(gè)對(duì)象正罢,什么接不接口的阵漏,煩不煩啊,JavaScript就是這么任性~~

我們的經(jīng)營(yíng)不斷拓展翻具,公司已經(jīng)有計(jì)劃的要引進(jìn)多種動(dòng)物履怯。我們現(xiàn)在需要若干個(gè)類(lèi)來(lái)管理各種動(dòng)物的叫聲,通過(guò)類(lèi)和接口相互約束裆泳,我們要寫(xiě)出擴(kuò)展性強(qiáng)叹洲、易于修改的代碼。

interface IBark{
    bark();
}
class cat implements IBark{
     bark(){
     console.log("喵喵")
     }
}
class dog implements IBark{
     bark(){
     console.log("旺旺")
     }
}
var catbark=new cat();
catbark.bark();//喵喵
var dogbark=new dog();
dogbark.bark();//旺旺

下面的代碼就是匯編而成的JavaScript工禾,由于沒(méi)有接口的約束运提,.bark命名并沒(méi)有硬性規(guī)定,所以想寫(xiě)成什么都可以闻葵。在這種小代碼上當(dāng)然看不出什么問(wèn)題民泵,甚至還會(huì)覺(jué)得下面的代碼比較好理解。當(dāng)成一個(gè)大系統(tǒng)槽畔、當(dāng)要系統(tǒng)修改時(shí)問(wèn)題就不少了栈妆。

var cat = (function () {
    function cat() {
    }
    cat.prototype.bark = function () {
        console.log("喵喵");
    };
    return cat;
}());
var dog = (function () {
    function dog() {
    }
    dog.prototype.bark = function () {
        console.log("旺旺");
    };
    return dog;
}());
var catbark = new cat();
catbark.bark();
var dogbark = new dog();
dogbark.bark();

最后來(lái)說(shuō)說(shuō)模塊,TypeScript的模塊分為內(nèi)部模塊、外部模塊鳞尔。

TypeScript也有外部模塊的概念嬉橙。使用外部模塊的兩種情況:node.js 和require.js,這里不做介紹寥假。

下面說(shuō)說(shuō)內(nèi)部模塊憎夷,“內(nèi)部模塊”現(xiàn)在稱(chēng)做“命名空間”。 “外部模塊”現(xiàn)在則簡(jiǎn)稱(chēng)為“模塊”昧旨。TypeScript 1.5里術(shù)語(yǔ)名已經(jīng)發(fā)生了變化拾给。module X {} 相當(dāng)于現(xiàn)在推薦的寫(xiě)法 namespace X {}。

最后設(shè)計(jì)一個(gè)稍微難點(diǎn)的程序兔沃,將上面的知識(shí)點(diǎn)做一個(gè)總結(jié):

我們假設(shè)蒋得,產(chǎn)品越來(lái)越多,從供應(yīng)商那里取得產(chǎn)品的編碼乒疏。但是供應(yīng)商很亂额衙,有時(shí)提供6位數(shù)編碼,有時(shí)提供產(chǎn)品名稱(chēng)怕吴。我們就用了正則表達(dá)式進(jìn)行核對(duì)窍侧,如果是6位數(shù)字的,那么加入編碼的數(shù)組转绷,如果是單純字母名稱(chēng)的伟件,加入名稱(chēng)數(shù)組。如果混合的议经,我們就當(dāng)它是廢品斧账。

開(kāi)頭我們就用上了namespace Vcode,然后再立接口煞肾,接口將返回一個(gè)boolean咧织,以及一個(gè)寫(xiě)入數(shù)組的方法。

namespace Vcode {
    export interface StringCode {
        isAcceptable(s: string): boolean;
        toarr(s);
    } //接口

    var nameRegexp = /^[A-Za-z]+$/;
    var CodeRegexp = /^[0-9]+$/;
    var namearr: string[] = [];
    var codearr: string[] = [];

    export class nameOnlyValidator implements StringCode {
        isAcceptable(s: string) {
            return nameRegexp.test(s);
        }
        toarr(s) {
            namearr.push(s);
        }
    }
    
    export class CodeValidator implements StringCode {
        isAcceptable(s: string) {
            return s.length === 6 && CodeRegexp.test(s);
        }
        toarr(s) {
            codearr.push(s);
        }

    }

    var strings: string[] = ['littDuck', '345633', 'No:177', 'alexzeng'];
    var namestring = new Vcode.nameOnlyValidator();
    var codestring = new Vcode.CodeValidator();
    for (var i in strings) {
        if (codestring.isAcceptable(strings[i])) {
            codestring.toarr(strings[i]);
        }
        if (namestring.isAcceptable(strings[i])) {
            namestring.toarr(strings[i]);
        }
    }
    console.log(namearr);
    console.log(codearr);
}

最終匯編成js文件:

var Vcode;
(function (Vcode) {
    var nameRegexp = /^[A-Za-z]+$/;
    var CodeRegexp = /^[0-9]+$/;
    var namearr = [];
    var codearr = [];
    var nameOnlyValidator = (function () {
        function nameOnlyValidator() {
        }
        nameOnlyValidator.prototype.isAcceptable = function (s) {
            return nameRegexp.test(s);
        };
        nameOnlyValidator.prototype.toarr = function (s) {
            namearr.push(s);
        };
        return nameOnlyValidator;
    }());
    Vcode.nameOnlyValidator = nameOnlyValidator;
    var outarr = (function () {
        function outarr() {
        }
        return outarr;
    }());
    Vcode.outarr = outarr;
    var CodeValidator = (function () {
        function CodeValidator() {
        }
        CodeValidator.prototype.isAcceptable = function (s) {
            return s.length === 6 && CodeRegexp.test(s);
        };
        CodeValidator.prototype.toarr = function (s) {
            codearr.push(s);
        };
        return CodeValidator;
    }());
    Vcode.CodeValidator = CodeValidator;
    var strings = ['littDuck', '345633', 'No:177', 'alexzeng'];
    var namestring = new Vcode.nameOnlyValidator();
    var codestring = new Vcode.CodeValidator();
    for (var i in strings) {
        if (codestring.isAcceptable(strings[i])) {
            codestring.toarr(strings[i]);
        }
        if (namestring.isAcceptable(strings[i])) {
            namestring.toarr(strings[i]);
        }
    }
    console.log(namearr);
    console.log(codearr);
})(Vcode || (Vcode = {}));

最后說(shuō)一下籍救,無(wú)論是module X {} 還是 namespace X {}习绢,匯編出來(lái)的js都是一樣的。

以上的例程蝙昙,全部是我自己碼出來(lái)的闪萄,想代碼比寫(xiě)文章困難,轉(zhuǎn)帖的時(shí)候請(qǐng)把涼風(fēng)有興或者AlexZeng.net進(jìn)行署名耸黑。本文版權(quán)聲明:自由轉(zhuǎn)載-非商用-非衍生-保持署名(創(chuàng)意共享3.0許可證

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末桃煎,一起剝皮案震驚了整個(gè)濱河市篮幢,隨后出現(xiàn)的幾起案子大刊,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,036評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缺菌,死亡現(xiàn)場(chǎng)離奇詭異葫辐,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)伴郁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)耿战,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人焊傅,你說(shuō)我怎么就攤上這事剂陡。” “怎么了狐胎?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵鸭栖,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我握巢,道長(zhǎng)晕鹊,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任暴浦,我火速辦了婚禮溅话,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘歌焦。我一直安慰自己飞几,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布独撇。 她就那樣靜靜地躺著循狰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪券勺。 梳的紋絲不亂的頭發(fā)上绪钥,一...
    開(kāi)封第一講書(shū)人閱讀 51,521評(píng)論 1 304
  • 那天,我揣著相機(jī)與錄音关炼,去河邊找鬼程腹。 笑死,一個(gè)胖子當(dāng)著我的面吹牛儒拂,可吹牛的內(nèi)容都是我干的寸潦。 我是一名探鬼主播,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼社痛,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼见转!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起蒜哀,我...
    開(kāi)封第一講書(shū)人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤斩箫,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體乘客,經(jīng)...
    沈念sama閱讀 45,644評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡狐血,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了易核。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片匈织。...
    茶點(diǎn)故事閱讀 39,953評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖牡直,靈堂內(nèi)的尸體忽然破棺而出缀匕,到底是詐尸還是另有隱情,我是刑警寧澤碰逸,帶...
    沈念sama閱讀 35,673評(píng)論 5 346
  • 正文 年R本政府宣布弦追,位于F島的核電站,受9級(jí)特大地震影響花竞,放射性物質(zhì)發(fā)生泄漏劲件。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評(píng)論 3 329
  • 文/蒙蒙 一约急、第九天 我趴在偏房一處隱蔽的房頂上張望零远。 院中可真熱鬧,春花似錦厌蔽、人聲如沸牵辣。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)纬向。三九已至,卻和暖如春戴卜,著一層夾襖步出監(jiān)牢的瞬間逾条,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,011評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工投剥, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留师脂,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,119評(píng)論 3 370
  • 正文 我出身青樓江锨,卻偏偏與公主長(zhǎng)得像吃警,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子啄育,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容