開始使用 TypeScript 和 React

Tom Dale 和其他人有一些關(guān)于 TypeScript 比較好的博文灭红,跟隨這些博文蔬啡,我最近開始使用 TypeScript。今天钓辆,我將展示如何從零開始建立一個(gè) TypeScript 工程手素,以及如何使用 Webpack 管理構(gòu)建過程祖搓。我也將陳述關(guān)于 TypeScript 的第一印象佑力,尤其是使用 TypeScript 和 ReactJS底桂。

我不會(huì)深入到 TypeScript 語法的具體細(xì)節(jié)植袍,你可以閱讀 TypeScript handbook 或者免費(fèi)書籍 TypeScript Deep Dive,它們是關(guān)于 TypeScript 比較好的入門材料籽懦。

更新:如果你想用德語閱讀這篇文章于个,你可以 thanks to the awesome folks at Reactx.de

安裝配置 TypeScript

第一步要做的事情是使用 Yarn 將 TypeScript 安裝到本地的node_modules目錄,首先猫十,使用yarn init創(chuàng)建一個(gè)工程:

yarn init yarn  add typescript

當(dāng)你安裝了 TypeScript览濒,你就可以使用 tsc 命令行工具呆盖,這個(gè)工具可以編譯 TypeScript,編譯時(shí)會(huì)創(chuàng)建一個(gè)開始文件 tsconfig.json贷笛,你可以編輯這個(gè)文件应又。你可以運(yùn)行 tsc --init 獲得這個(gè)文件 — 如果你已經(jīng)在本地安裝了 TypeScript,你需要運(yùn)行./node_modules/.bin/tsc --init乏苦。

注意: 你可以在我的點(diǎn)開頭的配置文件中看到株扛,我將 $PATH定義為./node_modules/.bin這個(gè)目錄。這有點(diǎn)危險(xiǎn)汇荐,因?yàn)槲铱赡懿唤?jīng)意地運(yùn)行這個(gè)目錄下的任何可執(zhí)行的文件洞就,但是我愿意承擔(dān)這個(gè)風(fēng)險(xiǎn),因?yàn)槲抑肋@個(gè)目錄下安裝了什么掀淘,而且這能節(jié)省很多打字時(shí)間旬蟋!

tsc --init 這個(gè)命令會(huì)生成一個(gè) tsconfig.json 文件,所有 TypeScript 編譯器的配置都存在于這個(gè)文件中革娄。在默認(rèn)配置的基礎(chǔ)上倾贰,我做了一些修改,下面是我正在用的一個(gè)配置:

{
  "compilerOptions": {
    "module": "es6", // 使用 ES2015 模塊
    "target": "es6", // 編譯成 ES2015 (Babel 將做剩下的事情)
    "allowSyntheticDefaultImports": true, // 看下面
    "baseUrl": "src", // 可以相對(duì)這個(gè)目錄 import 文件
    "sourceMap": true, // 使 TypeScript 生成 sourcemaps
    "outDir": "ts-build", // 構(gòu)建輸出目錄 (因?yàn)槲覀兇蟛糠謺r(shí)間都在使用 Webpack拦惋,所以不太相關(guān))
    "jsx": "preserve", // 開啟 JSX 模式, 但是 "preserve" 告訴 TypeScript 不要轉(zhuǎn)換它(我們將使用 Babel)
    "strict": true,
  },
  "exclude": [
    "node_modules" // 這個(gè)目錄下的代碼不會(huì)被 typescript 處理
  ]
}

allowSyntheticDefaultImports

將這個(gè)屬性的值設(shè)置為 true匆浙,它允許你使用 ES2015 默認(rèn)的 imports 風(fēng)格, 即使你導(dǎo)入的代碼沒有使用 ES2015 默認(rèn)的 export。

舉個(gè)例子厕妖,當(dāng)你 import 不是用 ES2015 編寫的 React 時(shí)(雖然源碼是首尼,但是 React 使用一個(gè)構(gòu)建好的版本),就可以利用上面的屬性設(shè)置言秸。這意味著软能,嚴(yán)格意義上來講,它沒有使用 ES2015 默認(rèn)的 export井仰,所以當(dāng)你使用 import 的時(shí)候埋嵌, TypeScript 會(huì)警告你。盡管如此俱恶,像 Webpack 這樣的構(gòu)建工具能夠?qū)胝_的代碼雹嗦,所以我將這個(gè)屬性設(shè)置為 true,相比使用 import * as React from 'react'合是,我更喜歡 import React from 'react'這種方式了罪。

strict:true

TypeScript 2.3 版本引入了一種新的配置選項(xiàng),strict聪全。當(dāng)將這個(gè)值設(shè)置為 true 時(shí)泊藕,TypeScript 編譯器會(huì)盡可能的嚴(yán)格 - 如果你將一些 JS 轉(zhuǎn)為 TS,這可能不是你想要的难礼,但是對(duì)于一些新的項(xiàng)目娃圆,使其盡可能的嚴(yán)格是有意義的玫锋。它還引入了一些不同的配置,其中幾個(gè)比較重要的的有noImplicitAnystrictNullChecks:

noImplicitAny

將 TypeScript 引入一個(gè)現(xiàn)有的項(xiàng)目讼呢,當(dāng)你不聲明變量的類型時(shí)撩鹿,TypeScript 不會(huì)拋出錯(cuò)誤。但是悦屏,當(dāng)我從零開始新建一個(gè) TypeScript 項(xiàng)目节沦,我希望編譯器盡可能地嚴(yán)格。 TypeScript 默認(rèn)做的一件事是將變量設(shè)置為any類型础爬。any是 TypeScript 中避免類型檢查的有效手段甫贯,它可以是任何值。當(dāng)你轉(zhuǎn)換 JavaScript 時(shí)看蚜,使用any是很有用的叫搁,但是最好還是盡可能地嚴(yán)格。當(dāng)將 noImplicitAny 設(shè)置為 true供炎,你必須為變量設(shè)置類型常熙。舉個(gè)例子,當(dāng)將noImplicitAny設(shè)置為 true 時(shí)碱茁,下面的代碼會(huì)報(bào)錯(cuò):

function log(thing) {
  console.log('thing', thing)
}

如果你想了解更多關(guān)于 noImplicitAny 的信息,可以閱讀TypeScript Deep Dive

strictNullChecks

這是另一個(gè)使 TypeScript 編譯器更嚴(yán)格的選項(xiàng)仿贬。TypeScript Deep Dive 這本書有一個(gè)很好的章節(jié)介紹這個(gè)選項(xiàng)纽竣。如果將這個(gè)選項(xiàng)設(shè)置為true,TypeScript 會(huì)更容易識(shí)別出你引用的一個(gè)可能是 undefined 值的地方茧泪,并將展示這個(gè)錯(cuò)誤蜓氨。例如:

person.age.increment()

當(dāng)將 strictNullChecks 設(shè)置為 true,TypeScript 會(huì)認(rèn)為 person 或者 person.age 可能是 undefined队伟,它會(huì)報(bào)個(gè)錯(cuò)以確保你處理它穴吹。這會(huì)防止出現(xiàn)運(yùn)行時(shí)錯(cuò)誤,所以這看起來是一個(gè)從一開始就要打開的很棒的選項(xiàng)嗜侮。

配置 Webpack, Babel and TypeScript

我是 Webpack 的腦殘粉港令;我喜歡它的插件生態(tài)系統(tǒng)、開發(fā)者工作流锈颗,喜歡它擅長管理復(fù)雜的應(yīng)用和構(gòu)建流程顷霹。所以,即使我們可能僅僅使用 TypeScript 編譯器击吱,我仍然喜歡引入 Webpack淋淀。因?yàn)?TypeScript 輸出 React 和 es6(也就是 es2015,babel 把 es6 轉(zhuǎn)成 es5覆醇,所以我們還需要 babel朵纷。讓我們安裝 Webpack炭臭,Babel 和相關(guān)的 presets 及 ts-loader,ts-loader 是 TypeScript 在 Webpack 中的插件袍辞。

還有 awesome-typescript-loader 鞋仍,也是 TypeScript 在 Webpack 中的插件,但是我首先找到的是 ts-loader 而且到目前為止它非常不錯(cuò)革屠。如果誰使用了 awesome-typescript-loader凿试,我很樂意看到關(guān)于它們兩者的對(duì)比。

yarn add webpack babel-core babel-loader babel-preset-es2015 babel-preset-react ts-loader webpack-dev-server

此時(shí)此刻似芝,我必須感謝 Tom Duncalf,他在博客中發(fā)表的 TypeScript 1.9 + React那婉,對(duì)我來說,是一個(gè)特別好的開始党瓮,我極力推薦它详炬。

在 Webpack 中沒有特別的配置,但是我還是在代碼中列出一些注釋來解釋它:

const webpack = require('webpack')
const path = require('path')

module.exports = {
  // 設(shè)置 sourcemaps 為 eval 模式寞奸,將模塊封裝到 eval 包裹起來
  devtool: 'eval',

  // 我們應(yīng)用的入口, 在 `src` 目錄 (我們添加到下面的 resolve.modules):
  entry: [
    'index.tsx'
  ],

  // 配置 devServer 的輸出目錄和 publicPath
  output: {
    filename: 'app.js',
    publicPath: 'dist',
    path: path.resolve('dist')
  },

  // 配置 devServer 
  devServer: {
    port: 3000,
    historyApiFallback: true,
    inline: true,
  },

  // 告訴 Webpack 加載 TypeScript 文件
  resolve: {
    // 首先尋找模塊中的 .ts(x) 文件, 然后是 .js 文件
    extensions: ['.ts', '.tsx', '.js'],

    // 在模塊中添加 src, 當(dāng)你導(dǎo)入文件時(shí)呛谜,可以將 src 作為相關(guān)路徑
    modules: ['src', 'node_modules'],
  },

  module: {
    loaders: [
      // .ts(x) 文件應(yīng)該首先經(jīng)過 Typescript loader 的處理, 然后是 babel 的處理
      { test: /\.tsx?$/, loaders: ['babel-loader', 'ts-loader'], include: path.resolve('src') }
    ]
  },
}

我們按照上面的方式配置 loaders ,從而使.ts(x)文件首先經(jīng)過ts-loader的處理枪萄。按照tsconfig.json中的配置隐岛,使用 TypeScript 編譯.ts(x)文件 - 輸出ES2015。然后瓷翻,我們使用 Babel 將它降級(jí)到 ES5聚凹。為了實(shí)現(xiàn)這些,我創(chuàng)建了一個(gè)包含需要的 presets 的.babelrc文件:

{
  "presets": ["es2015", "react"]
}

現(xiàn)在我們已經(jīng)做好了寫 TypeScript 應(yīng)用的準(zhǔn)備齐帚。

寫一個(gè) TypeScript React 組件

現(xiàn)在妒牙,我們準(zhǔn)備好建立src/index.tsx,這是我們這個(gè)應(yīng)用的入口对妄。我們可以創(chuàng)建一個(gè)虛擬的組件湘今,渲染它,查看它是否正常運(yùn)行剪菱。

import React from 'react'
import ReactDOM from 'react-dom'

const App = () => {
  return (
    <div>
      <p>Hello world!</p>
    </div>
  )
}

ReactDOM.render(<App />, document.getElementById('app'))

如果你運(yùn)行 webpack摩瞎,會(huì)看到下面的錯(cuò)誤:

ERROR in ./src/index.tsx
(1,19): error TS2307: Cannot find module 'react'.

ERROR in ./src/index.tsx
(2,22): error TS2307: Cannot find module 'react-dom'.

發(fā)生上面的錯(cuò)誤是因?yàn)?TypeScript 試圖確認(rèn) React 的類型、React 導(dǎo)出了什么孝常。對(duì)于 React DOM愉豺,TypeScript 會(huì)做同樣的事情。React 并不是使用 TypeScript 編寫的茫因,所以它并沒有包含那些信息蚪拦。幸運(yùn)地是,為了應(yīng)對(duì)這種情況,社區(qū)已經(jīng)創(chuàng)建了 DefinitelyTyped驰贷,這是一個(gè)大型的組件類型庫盛嘿。

最近,安裝機(jī)制改變了括袒;所有的類型被發(fā)布到 npm @types scope 下次兆。為了獲得 React 和 ReactDOM 的類型,我們運(yùn)行下面的命令:

yarn add @types/react
yarn add @types/react-dom

通過上面的處理锹锰,錯(cuò)誤不見了芥炭。無論何時(shí),你安裝一個(gè)依賴時(shí)恃慧,都應(yīng)該試著安裝@types包园蝠,或者你想查看是否有被支持的類型,你可以在TypeSearch網(wǎng)站上查看痢士。

本地運(yùn)行 app

為了在本地運(yùn)行 app彪薛,我們只需要運(yùn)行webpack-dev-server命令。我配置了一個(gè)腳本start, 它能做上面的事情:

"scripts": {
  "start": "webpack-dev-server"
}

服務(wù)會(huì)找到 webpack.config.json這個(gè)文件怠蹂,使用它創(chuàng)建我們的應(yīng)用善延。

如果你運(yùn)行 yarn start,你會(huì)看到來自于 webpack-dev-server 的輸出,包含ts-loader 的輸出城侧,這些能夠確認(rèn)應(yīng)用是否正常運(yùn)行易遣。

$ webpack-dev-server
Project is running at http://localhost:3000/
webpack output is served from /dist
404s will fallback to /index.html
ts-loader: Using typescript@2.3.0 and /Users/jackfranklin/git/interactive-react-introduction/tsconfig.json
Version: webpack 2.4.1
Time: 6077ms
 Asset     Size  Chunks                    Chunk Names
app.js  1.14 MB       0  [emitted]  [big]  main
webpack: Compiled successfully.

為了能夠在本地看到效果,我創(chuàng)建了一個(gè) index.html 文件嫌佑,讓它加載編譯后的代碼:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>My Typescript App</title>
  </head>
  <body>
    <div id="app"></div>
    <script src="dist/app.js"></script>
  </body>

定義一個(gè)模塊類型

在現(xiàn)在的工程中训挡,我想使用 React Ace module 包含一個(gè)代碼編輯器。但是這個(gè)模塊并不提供 types歧强,并且也沒有 @types/react-ace。在這種情況下为肮,我們必須在應(yīng)用中增加類型摊册,這樣可以使 TypeScript 知道如何去檢查它的類型。這看起來非常煩人颊艳,讓 TypeScript 至少知道所有第三方依賴關(guān)系的好處是茅特,可以節(jié)省調(diào)試時(shí)間。

定義一個(gè)只包含類型的文件棋枕,后綴是 .d.ts( ‘d‘ 代表 ‘declaration‘ )白修,你可以從 TypeScript docs 了解更多。在你的工程中重斑,TypeScript 將會(huì)自動(dòng)地找到這些文件兵睛,你不需要顯式地導(dǎo)入它們。

我創(chuàng)建了 react-ace.d.ts 文件,添加下面的代碼祖很,創(chuàng)建模塊笛丙,定義它的默認(rèn) export 為一個(gè) React 組件。

declare module 'react-ace' {
    interface ReactAceProps {
      mode: string
      theme: string
      name: string
      editorProps?: {}
      showPrintMargin?: boolean
      minLines?: number
      maxLines?: number
      wrapEnabled?: boolean
      value: string
      highlightActiveLine?: boolean
      width?: string
      fontSize?: number
    }

    const ReactAce: React.ComponentClass<ReactAceProps>
    export = ReactAce
}

我首先創(chuàng)建了一個(gè) TypeScript 接口假颇,這個(gè)接口包含組件的屬性胚鸯,export = ReactAce標(biāo)明組件通過模塊被導(dǎo)出。通過定義屬性的類型笨鸡,TypeScript 會(huì)告訴我是否弄錯(cuò)了屬性的類型或者忘記設(shè)置一個(gè)類型姜钳,這是非常有價(jià)值的。

測試

最后形耗,使用 TypeScript哥桥,我也想有一個(gè)很好的測試方案。我是 Facebook 的 Jest 的超級(jí)粉絲趟脂,我在 google 上做了一些搜索泰讽,確認(rèn)它是否能用 TypeScript 運(yùn)行。結(jié)果發(fā)現(xiàn)昔期,這是可行的已卸,ts-jest 包可以做一些很重的轉(zhuǎn)換。除此之外硼一,還有一個(gè)做類型檢查的 @types/jest 包累澡,可以讓你所有的測試都是類型確認(rèn)過的。

非常感謝 RJ Zaworski般贼,他在博客上發(fā)表了 TypeScript and Jest 愧哟,這使我開始了解這個(gè)主題。如果你安裝了 ts-jest哼蛆,你只需要在 package.json 中配置 Jest蕊梧,下面是配置:

"jest": {
  "moduleFileExtensions": [
    "ts",
    "tsx",
    "js"
  ],
  "transform": {
    "\\.(ts|tsx)$": "<rootDir>/node_modules/ts-jest/preprocessor.js"
  },
  "testRegex": "/*.spec.(ts|tsx|js)$"
},

第一個(gè)配置告訴 Jest 尋找.ts.tsx 文件。 transform 對(duì)象告訴 Jest 通過 ts-jest 預(yù)處理器運(yùn)行任何 TypeScript 文件腮介,ts-jest 預(yù)處理器通過 TypeScript 編譯器運(yùn)行 TypeScript 文件肥矢,產(chǎn)出能讓 Jest 識(shí)別的 JavaScript。最后叠洗,我更新了 testRegex 設(shè)置甘改,目的是尋找任何 *.spec.ts(x) 文件,我更喜歡用這種方式命名轉(zhuǎn)換灭抑。

通過上面這些配置十艾,我可以運(yùn)行 jest 并且讓每一件事情都如預(yù)期一樣運(yùn)行。

使用 TSLint 規(guī)范代碼

盡管 TypeScript 在代碼中會(huì)給出很多檢查提示腾节,我仍然想要一個(gè)規(guī)范器忘嫉,做些代碼風(fēng)格和質(zhì)量檢查荤牍。就像 JavaScript 的 ESLint,TSLint 是檢查 TypeScript 的最好選擇榄融。它和 ESlint 的工作方式相同 - 用一系列生效或不生效的規(guī)則参淫,還有一個(gè) TSLint-React 包增加 React 的具體規(guī)則。

你可以通過 tslint.json 文件配置 TSLint愧杯,我的配置文件如下涎才。我用 tslint:latest 和 tslint-react presets,它們可以使用很多規(guī)則力九。我不贊成一些默認(rèn)設(shè)置耍铜,所以我重寫了它們 - 你可以和我的配置不同 - 這完全取決于你!

{
    "defaultSeverity": "error",
    "extends": ["tslint:latest", "tslint-react"],
    "jsRules": {},
    "rules": {
      // 用單引號(hào), 但是在 JSX 中跌前,強(qiáng)制使用雙引號(hào)
      "quotemark": [true, "single", "jsx-double"],
      // 我更喜歡沒有分號(hào) :)
      "semicolon": [true, "never"],
      // 這個(gè)規(guī)則使每個(gè)接口以 I 開頭棕兼,這點(diǎn)我不喜歡
      "interface-name": [true, "never-prefix"],
      // 這個(gè)規(guī)則強(qiáng)制對(duì)象中的 key 按照字母順序排列 
      "object-literal-sort-keys": false
    },
    "rulesDirectory": []
}

我可以運(yùn)行tslint --project tsconfig.json規(guī)范我的項(xiàng)目

結(jié)論

總之,到目前為止抵乓,用 TypeScript 開發(fā)我很高興伴挚。我肯定會(huì)發(fā)表更多博文來描述這門語言的細(xì)節(jié)和我是如何使用 TypeScript 的。但僅就如下操作而言灾炭,構(gòu)建過程茎芋、配置所有的工具、開始使用類型蜈出,這真是一種享受田弥。如果你正在將你的 JS 應(yīng)用結(jié)構(gòu)化,想要一個(gè)更強(qiáng)大的編譯器避免錯(cuò)誤并減少調(diào)試時(shí)間铡原,我極力推薦你嘗試 TypeScript偷厦。

如果你想看源碼或者以本文中的例子作為開始,我在 GitHub 上放了一個(gè)例子燕刻,如果你有任何問題只泼,可以提 issue。

文章轉(zhuǎn)自:Github
文章地址:翻譯 | 開始使用 TypeScript 和 React

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末卵洗,一起剝皮案震驚了整個(gè)濱河市请唱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌忌怎,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件酪夷,死亡現(xiàn)場離奇詭異榴啸,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來醇份,“玉大人吝沫,你說我怎么就攤上這事须蜗」复澹” “怎么了躏结?”我有些...
    開封第一講書人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵劫狠,是天一觀的道長潜的。 經(jīng)常有香客問我骚揍,道長,這世上最難降的妖魔是什么啰挪? 我笑而不...
    開封第一講書人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任信不,我火速辦了婚禮,結(jié)果婚禮上亡呵,老公的妹妹穿的比我還像新娘抽活。我一直安慰自己,他們只是感情好锰什,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開白布下硕。 她就那樣靜靜地躺著,像睡著了一般汁胆。 火紅的嫁衣襯著肌膚如雪梭姓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,441評(píng)論 1 310
  • 那天沦泌,我揣著相機(jī)與錄音糊昙,去河邊找鬼。 笑死谢谦,一個(gè)胖子當(dāng)著我的面吹牛释牺,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播回挽,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼没咙,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了千劈?” 一聲冷哼從身側(cè)響起祭刚,我...
    開封第一講書人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎墙牌,沒想到半個(gè)月后涡驮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡喜滨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年捉捅,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片虽风。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡棒口,死狀恐怖寄月,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情无牵,我是刑警寧澤漾肮,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站茎毁,受9級(jí)特大地震影響克懊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜充岛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一保檐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧崔梗,春花似錦夜只、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至谈为,卻和暖如春旅挤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背伞鲫。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來泰國打工粘茄, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人秕脓。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓柒瓣,卻偏偏與公主長得像,于是被迫代替她去往敵國和親吠架。 傳聞我的和親對(duì)象是個(gè)殘疾皇子芙贫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359