React 17新特性:無新特性

本文翻譯自React官網(wǎng): React v17.0 Release Candidate: No New Features


今天配紫,我們正在發(fā)布React 17的第一個(gè)候選發(fā)布版厦凤。距離上一個(gè)主要的React版本已經(jīng)過去了兩年半鹿驼,即使按照我們的標(biāo)準(zhǔn),也已經(jīng)很長時(shí)間了!在此博客文章中微宝,我們將描述此主要版本的作用摄凡,可以期望的主要變化以及如何試用該版本。

沒有新功能

React 17版本不尋常畏妖,因?yàn)樗鼪]有添加任何面向開發(fā)人員的新功能。取而代之的是疼阔,此發(fā)行版主要側(cè)重于使其更易于升級React本身戒劫。

我們正在積極開發(fā)新的React功能,但它們不是此版本的一部分婆廊。React 17發(fā)行版是我們將其推廣到任何人的戰(zhàn)略的關(guān)鍵部分迅细。

特別地,React 17是一個(gè)“墊腳石”版本淘邻,它使將由一個(gè)版本的React管理的樹嵌入到由另一個(gè)版本的React管理的樹中更加安全茵典。

逐步升級

在過去的七年中,React升級一直是“全有或全無”列荔。您可以使用舊版本敬尺,也可以將整個(gè)應(yīng)用升級到新版本。中間沒有贴浙。

到目前為止砂吞,這已經(jīng)解決了,但是我們遇到了“全有或全無”升級策略的局限性崎溃。某些API更改(例如蜻直,不贊成使用舊版上下文API)是不可能以自動(dòng)化方式進(jìn)行的。即使今天編寫的大多數(shù)應(yīng)用程序從未使用過它們袁串,我們?nèi)匀辉赗eact中支持它們概而。我們必須選擇無限期地在React中支持它們,還是將某些應(yīng)用程序留在舊版本的React中囱修。這兩個(gè)選項(xiàng)都不是很好赎瑰。

因此,我們想提供另一種選擇破镰。

React 17支持逐步的React升級餐曼。從React 15升級到16(或者很快從React 16升級到17)時(shí)压储,通常會立即升級整個(gè)應(yīng)用程序。這適用于許多應(yīng)用程序源譬。但是集惋,如果代碼庫是在幾年前編寫的,并且沒有得到積極維護(hù)踩娘,則挑戰(zhàn)可能會越來越大刮刑。盡管可以在頁面上使用兩個(gè)版本的React,但是直到React 17仍然脆弱养渴,并導(dǎo)致事件問題雷绢。

我們正在使用React 17解決許多這些問題。這意味著當(dāng)React 18和下一個(gè)未來版本問世時(shí)厚脉,您現(xiàn)在將有更多選擇习寸。第一種選擇是像以前一樣,一次升級整個(gè)應(yīng)用程序傻工。但是您也可以選擇逐個(gè)升級您的應(yīng)用程序。例如孵滞,您可能決定將大部分應(yīng)用程序遷移到React 18中捆,但在React 17上保留一些延遲加載的對話框或子路由。

這并不意味著您必須逐步升級坊饶。對于大多數(shù)應(yīng)用程序泄伪,一次全部升級仍然是最好的解決方案。加載兩個(gè)版本的React(即使其中一個(gè)是按需延遲加載)仍然不是理想的選擇匿级。但是蟋滴,對于沒有積極維護(hù)的大型應(yīng)用程序,可以考慮使用此選項(xiàng)痘绎,并且React 17可以使這些應(yīng)用程序不落伍津函。

要啟用漸進(jìn)式更新,我們需要對React事件系統(tǒng)進(jìn)行一些更改孤页。React 17是主要版本尔苦,因?yàn)檫@些更改可能會被破壞。實(shí)際上行施,我們只需要在100,000個(gè)以上的組件中更改少于二十個(gè)組件允坚,因此我們希望大多數(shù)應(yīng)用程序可以升級到React 17而不會帶來太多麻煩

逐步升級演示

我們準(zhǔn)備了一個(gè)例子展示了如何在必要時(shí)延遲加載舊版本的React蛾号。該演示使用Create React App稠项,但應(yīng)該可以對其他工具采用類似的方法。我們歡迎使用其他工具作為拉取請求的演示鲜结。

我們已將其他更改推遲到React 17之后展运。此版本的目標(biāo)是實(shí)現(xiàn)逐步升級活逆。如果升級到React 17太困難了,那將無法實(shí)現(xiàn)其目標(biāo)乐疆。

對事件委派的更改

從技術(shù)上講划乖,始終可以嵌套使用不同版本的React開發(fā)的應(yīng)用程序。但是挤土,由于React事件系統(tǒng)的工作原理琴庵,它相當(dāng)脆弱。

在React組件中仰美,通常會內(nèi)聯(lián)編寫事件處理程序:

<button onClick={handleClick}>

等效于此代碼的原始DOM類似于:

myButton.addEventListener('click', handleClick);

但是迷殿,對于大多數(shù)事件,React實(shí)際上不會將它們附加到在其上聲明它們的DOM節(jié)點(diǎn)上咖杂。相反庆寺,React會直接在document節(jié)點(diǎn)上為每種事件類型附加一個(gè)處理程序。這稱為事件委托诉字。除了在大型應(yīng)用程序樹上具有性能優(yōu)勢外懦尝,它還使添加新功能(如重播事件)更加容易。

自從第一個(gè)版本發(fā)布以來壤圃,React一直在自動(dòng)進(jìn)行事件委派陵霉。當(dāng)文檔上觸發(fā)DOM事件時(shí),React會找出要調(diào)用的組件伍绳,然后React事件會在整個(gè)組件中“冒泡”踊挠。但是在幕后,本機(jī)事件已經(jīng)冒出來冲杀,達(dá)到了documentReact安裝其事件處理程序的水平效床。

但是,這是逐步升級的問題权谁。

如果頁面上有多個(gè)React版本剩檀,它們都將在頂部注冊事件處理程序。這將中斷e.stopPropagation():如果嵌套樹停止了事件的傳播闯传,則外部樹仍將接收該事件谨朝。這使得嵌套不同版本的React變得很困難。這種擔(dān)心不是假設(shè)的甥绿,例如字币,Atom編輯器在四年前就遇到了這種情況

這就是為什么我們要改變React在幕后將事件附加到DOM的方式共缕。

在React 17中洗出,React將不再在該document級別附加事件處理程序。相反图谷,它將把它們附加到渲染您的React樹的根DOM容器中:

const rootNode = document.getElementById('root');
ReactDOM.render(<App />, rootNode);

在React 16和更早的版本中翩活,React會document.addEventListener()處理大多數(shù)事件阱洪。React 17將rootNode.addEventListener()在后臺調(diào)用。

該圖顯示了React 17如何將事件附加到根而不是文檔

由于此更改菠镇,現(xiàn)在可以更安全地將由一個(gè)版本管理的React樹嵌入到由其他React版本管理的樹中冗荸。請注意,要使其正常工作利耍,兩個(gè)版本都必須為17或更高版本蚌本,這就是為什么升級到React 17很重要的原因。從某種意義上說隘梨,React 17是一個(gè)“墊腳石”版本程癌,使下一個(gè)逐步升級成為可能。

這一變化還使將React嵌入到使用其他技術(shù)構(gòu)建的應(yīng)用程序中變得更加容易轴猎。例如嵌莉,如果應(yīng)用程序的外部“外殼”是用jQuery編寫的,但其中的較新代碼是用React編寫的捻脖,e.stopPropagation()那么React代碼內(nèi)部現(xiàn)在將阻止它到達(dá)jQuery代碼-正如您所期望的那樣锐峭。這在另一個(gè)方向上也起作用。如果您不再喜歡React并想重寫您的應(yīng)用程序(例如可婶,在jQuery中)只祠,則可以開始將外殼從React轉(zhuǎn)換為jQuery,而不會破壞事件傳播扰肌。

我們已經(jīng)證實(shí),很多 問題 報(bào)道 我們的 問題 跟蹤器與整合與之反應(yīng)的非反應(yīng)的代碼已經(jīng)被固定在新的行為熊杨。

您可能想知道這是否會破壞根容器之外的Portal曙旭。答案是,React偵聽門戶網(wǎng)站容器上的事件晶府,因此這不是問題桂躏。

解決潛在問題

與任何重大更改一樣,可能需要調(diào)整一些代碼川陆。在Facebook剂习,我們必須調(diào)整總共約10個(gè)模塊(成千上萬個(gè)模塊)以適應(yīng)此更改。

例如较沪,如果您通過添加手動(dòng)DOM偵聽器document.addEventListener(...)鳞绕,則可能希望它們捕獲所有React事件。在React 16及更早版本中尸曼,即使您調(diào)用e.stopPropagation()React事件處理程序们何,您的自定義document偵聽器仍會收到它們,因?yàn)楸緳C(jī)事件已經(jīng)在文檔級別控轿。使用React 17冤竹,傳播停止(按要求7鞣狻),因此您的document處理程序?qū)⒉粫|發(fā):

document.addEventListener('click', function() {
  // This custom handler will no longer receive clicks
  // from React components that called e.stopPropagation()
});

您可以通過將偵聽器轉(zhuǎn)換為使用捕獲階段來修復(fù)此類代碼鹦蠕。為此冒签,您可以將{ capture: true }第三個(gè)參數(shù)傳遞給document.addEventListener

document.addEventListener('click', function() {
  // Now this event handler uses the capture phase,
  // so it receives *all* click events below!
}, { capture: true });

請注意,此策略在整體上如何更具彈性-例如钟病,它可能會修復(fù)代碼中在e.stopPropagation()React事件處理程序外部調(diào)用時(shí)發(fā)生的現(xiàn)有錯(cuò)誤萧恕。換句話說,React 17中的事件傳播更接近常規(guī)DOM档悠。

其他重大變化

我們將React 17中的重大更改保持在最低水平廊鸥。例如,它不會刪除以前版本中已棄用的任何方法辖所。但是惰说,它的確包含一些其他重大更改,根據(jù)我們的經(jīng)驗(yàn)缘回,這些更改相對安全吆视。總體而言酥宴,由于這些因素啦吧,我們必須在100,000+個(gè)組件中調(diào)整少于20個(gè)。

與瀏覽器對應(yīng)

我們對事件系統(tǒng)進(jìn)行了一些較小的更改:

  • onScroll事件不再冒泡拙寡, 以防止常見的混亂授滓。
  • ReactonFocusonBlurevent已轉(zhuǎn)為使用幕后的nativefocusinfocusoutevents,這與React的現(xiàn)有行為更加接近肆糕,有時(shí)還會提供額外的信息般堆。
  • 捕獲階段事件(例如onClickCapture)現(xiàn)在使用真實(shí)的瀏覽器捕獲階段偵聽器。

這些更改使React與瀏覽器行為更加接近诚啃,并提高了互操作性淮摔。

盡管該事件從React 17切換focusfocusin 了幕后,但onFocus請注意始赎,這并未影響冒泡行為和橙。在React中,onFocus事件總是冒泡的造垛,它在React 17中繼續(xù)冒泡魔招,因?yàn)橥ǔK且粋€(gè)更有用的默認(rèn)值。請參閱此沙箱筋搏,了解可以針對不同的特定用例添加的不同檢查仆百。

沒有事件池

React 17從React移除了“事件池”優(yōu)化。它不會提高現(xiàn)代瀏覽器的性能奔脐,甚至?xí)菇?jīng)驗(yàn)豐富的React用戶感到困惑:

function handleChange(e) {
  setData(data => ({
    ...data,
    // This crashes in React 16 and earlier:
    text: e.target.value
  }));
}

這是因?yàn)镽eact在舊瀏覽器中重用了不同事件之間的事件對象以提高性能俄周,并將所有事件字段都設(shè)置null在它們之間吁讨。在React 16及更早版本中,您必須調(diào)用e.persist()以正確使用該事件峦朗,或讀取您之前需要的屬性建丧。

在React 17中,此代碼可以按您期望的那樣工作波势。舊的事件池優(yōu)化已被完全刪除翎朱,因此您可以在需要時(shí)閱讀事件字段。

這是一種行為更改尺铣,這就是我們將其標(biāo)記為破壞的原因拴曲,但實(shí)際上,在Facebook上我們還沒有看到它破壞任何東西凛忿。(也許它甚至修復(fù)了一些錯(cuò)誤3鹤啤)請注意,e.persist()React事件對象仍然可用店溢,但是現(xiàn)在它什么也沒做叁熔。

高效的清理

我們正在使useEffect清理功能的時(shí)間更加一致。

useEffect(() => {
  // This is the effect itself.
  return () => {    // This is its cleanup.  };});

大多數(shù)效果不需要延遲屏幕更新床牧,因此React在屏幕上反映出更新后立即異步運(yùn)行它們荣回。(在極少數(shù)情況下,您需要一種效果來阻止油漆戈咳,例如心软,測量和定位工具提示,請使用useLayoutEffect著蛙。)

但是糯累,在卸載組件時(shí),效果清理函數(shù)將用于同步運(yùn)行(類似于componentWillUnmount類中的同步)册踩。我們發(fā)現(xiàn)這不適用于大型應(yīng)用程序,因?yàn)樗鼤p慢大屏幕過渡(例如切換選項(xiàng)卡)的速度效拭。

在React 17中暂吉,清除功能始終異步運(yùn)行-例如,如果要卸載組件缎患,則在更新屏幕運(yùn)行清除慕的。**

這反映了效果本身如何更緊密地運(yùn)行。在極少數(shù)情況下挤渔,您可能希望依靠同步執(zhí)行肮街,可以useLayoutEffect改為使用。

您可能想知道這是否意味著您現(xiàn)在將無法修復(fù)有關(guān)setState未安裝組件的警告判导。別擔(dān)心-專門針對這種情況作出反應(yīng)檢查嫉父,確實(shí)沒有觸發(fā)setState在卸載和清理之間的短間隔警告沛硅。因此,取消代碼的請求或間隔幾乎總是可以保持不變绕辖。

另外摇肌,React 17將在運(yùn)行任何新效果之前始終執(zhí)行所有效果清理功能(針對所有組件)。React 16僅保證組件中效果的這種順序仪际。

潛在問題

盡管可重用的庫可能需要對其進(jìn)行更徹底的測試围小,但我們僅看到幾個(gè)組件隨此更改而中斷。有問題的代碼的一個(gè)示例可能如下所示:

useEffect(() => {
  someRef.current.someSetupMethod();
  return () => {
    someRef.current.someCleanupMethod();
  };
});

問題是someRef.current可變的树碱,因此在運(yùn)行清除功能時(shí)肯适,可能已將其設(shè)置為null。解決方案是捕獲效果內(nèi)的任何可變值:

useEffect(() => {
  const instance = someRef.current;
  instance.someSetupMethod();
  return () => {
    instance.someCleanupMethod();
  };
});

我們不希望這是一個(gè)常見的問題成榜,因?yàn)?a target="_blank">我們的eslint-plugin-react-hooks/exhaustive-deps(請確保您使用它?蛱颉)始終對此發(fā)出警告。

返回未定義的一致錯(cuò)誤

在React 16和更早的版本中伦连,返回undefined始終是一個(gè)錯(cuò)誤:

function Button() {
  return; // Error: Nothing was returned from render
}

這部分是因?yàn)楹苋菀?code>undefined無意地返回:

function Button() {
  // We forgot to write return, so this component returns undefined.
  // React surfaces this as an error instead of ignoring it.
  <button />;
}

以前雨饺,React僅對類和函數(shù)組件執(zhí)行此操作,但不檢查forwardRefandmemo組件的返回值惑淳。這是由于編碼錯(cuò)誤额港。

在React 17中,forwardRefmemo組件的行為與常規(guī)函數(shù)和類組件一致歧焦。undefined從他們那里回來是錯(cuò)誤的移斩。

let Button = forwardRef(() => {
  // We forgot to write return, so this component returns undefined.
  // React 17 surfaces this as an error instead of ignoring it.
  <button />;
});

let Button = memo(() => {
  // We forgot to write return, so this component returns undefined.
  // React 17 surfaces this as an error instead of ignoring it.
  <button />;
});

對于您要有意不渲染任何內(nèi)容的情況,請改為返回null绢馍。

本機(jī)組件堆棧

當(dāng)您在瀏覽器中引發(fā)錯(cuò)誤時(shí)向瓷,瀏覽器會為您提供帶有JavaScript函數(shù)名稱及其位置的堆棧跟蹤。但是舰涌,JavaScript堆棧通常不足以診斷問題猖任,因?yàn)镽eact樹的層次結(jié)構(gòu)可能同樣重要。您不僅要知道Button引發(fā)了錯(cuò)誤瓷耙,還想知道在React樹中的哪個(gè)位置Button朱躺。

為了解決這個(gè)問題,當(dāng)您遇到錯(cuò)誤時(shí)搁痛,React 16開始打印“組件堆棾げ螅”。盡管如此鸡典,它們?nèi)匀徊蝗缭鶭avaScript堆棧源请。特別是,它們在控制臺中不可單擊,因?yàn)镽eact不知道函數(shù)在源代碼中聲明的位置谁尸。此外舅踪,它們在生產(chǎn)中幾乎毫無用處。與常規(guī)的最小化JavaScript堆椫⑿冢可以通過源映射自動(dòng)恢復(fù)到原始函數(shù)名稱不同硫朦,使用React組件堆棧,您必須在生產(chǎn)堆棧和捆綁包大小之間進(jìn)行選擇背镇。

在React 17中咬展,使用不同的機(jī)制生成組件堆棧,該機(jī)制將它們與常規(guī)的本機(jī)JavaScript堆椔髡叮縫合在一起破婆。這使您可以在生產(chǎn)環(huán)境中獲得完全符號化的React組件堆棧跟蹤。

React實(shí)現(xiàn)這一點(diǎn)的方式有些不合常規(guī)胸囱。當(dāng)前祷舀,瀏覽器沒有提供獲取函數(shù)的堆棧框架(源文件和位置)的方法烹笔。因此裳扯,當(dāng)React捕獲到錯(cuò)誤時(shí),它現(xiàn)在將通過在可能的情況下從上面每個(gè)組件內(nèi)部拋出(并捕獲)一個(gè)臨時(shí)錯(cuò)誤來重建其組件堆棧谤职。這會增加少量的崩潰性能損失饰豺,但是每個(gè)組件類型只會發(fā)生一次。

如果您感到好奇允蜈,可以在pull請求中閱讀更多詳細(xì)信息冤吨,但是在大多數(shù)情況下,這種確切的機(jī)制不會影響您的代碼饶套。從您的角度來看漩蟆,新功能是現(xiàn)在可以單擊組件堆棧(因?yàn)樗鼈円蕾囉诒緳C(jī)瀏覽器堆棧框架)妓蛮,并且可以像常規(guī)JavaScript錯(cuò)誤那樣在生產(chǎn)中對其進(jìn)行解碼怠李。

構(gòu)成重大變化的部分是,要使此工作正常進(jìn)行蛤克,React將在捕獲錯(cuò)誤后在堆棧中重新執(zhí)行上面某些React函數(shù)和React類構(gòu)造函數(shù)的部分扔仓。由于渲染函數(shù)和類構(gòu)造函數(shù)不應(yīng)具有副作用(這對于服務(wù)器渲染也很重要),因此這不應(yīng)引起任何實(shí)際問題咖耘。

刪除私有導(dǎo)出

最后,最后一個(gè)值得注意的重大變化是我們刪除了一些以前暴露給其他項(xiàng)目的React內(nèi)部組件撬码。特別是儿倒,React Native for Web過去曾經(jīng)依賴于事件系統(tǒng)的某些內(nèi)部組件,但是這種依賴關(guān)系是脆弱的并且經(jīng)常被破壞。

在React 17中夫否,這些私有導(dǎo)出已被刪除彻犁。據(jù)我們所知,React Native for Web是唯一使用它們的項(xiàng)目凰慈,并且他們已經(jīng)完成了向不依賴于那些私有導(dǎo)出的其他方法的遷移汞幢。

這意味著舊版本的React Native for Web不會與React 17兼容,但是新版本將與它兼容微谓。實(shí)際上森篷,這并沒有太大變化,因?yàn)镽eact Native for Web必須發(fā)布新版本以適應(yīng)內(nèi)部React更改豺型。

此外仲智,我們還刪除了ReactTestUtils.SimulateNative輔助方法。他們從未被記錄下來姻氨,沒有按照他們的名字所暗示的那樣去做钓辆,并且不能與我們對事件系統(tǒng)所做的更改一起使用。如果您想要一種方便的方法來在測試中觸發(fā)本機(jī)瀏覽器事件肴焊,請查看React測試庫前联。

參考

React v17.0 Release Candidate: No New Features

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市娶眷,隨后出現(xiàn)的幾起案子似嗤,更是在濱河造成了極大的恐慌,老刑警劉巖茂浮,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件双谆,死亡現(xiàn)場離奇詭異,居然都是意外死亡席揽,警方通過查閱死者的電腦和手機(jī)顽馋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來幌羞,“玉大人寸谜,你說我怎么就攤上這事∈翳耄” “怎么了熊痴?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長聂宾。 經(jīng)常有香客問我果善,道長,這世上最難降的妖魔是什么系谐? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任巾陕,我火速辦了婚禮讨跟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鄙煤。我一直安慰自己晾匠,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布梯刚。 她就那樣靜靜地躺著凉馆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪亡资。 梳的紋絲不亂的頭發(fā)上澜共,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天,我揣著相機(jī)與錄音沟于,去河邊找鬼咳胃。 笑死,一個(gè)胖子當(dāng)著我的面吹牛旷太,可吹牛的內(nèi)容都是我干的展懈。 我是一名探鬼主播,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼供璧,長吁一口氣:“原來是場噩夢啊……” “哼存崖!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起睡毒,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤来惧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后演顾,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體供搀,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年钠至,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了葛虐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,013評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡棉钧,死狀恐怖屿脐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情宪卿,我是刑警寧澤的诵,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站佑钾,受9級特大地震影響西疤,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜休溶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一代赁、第九天 我趴在偏房一處隱蔽的房頂上張望撒遣。 院中可真熱鬧,春花似錦管跺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至泻云,卻和暖如春艇拍,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背宠纯。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工卸夕, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人婆瓜。 一個(gè)月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓快集,卻偏偏與公主長得像,于是被迫代替她去往敵國和親廉白。 傳聞我的和親對象是個(gè)殘疾皇子个初,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評論 2 355