小程序框架:WePY/mpvue/uni-app/Taro

2017-1-9微信小程序誕生以來,歷經2年多的迭代升級,已有數百萬小程序上線,成為繼Web、iOS、Android之后,第四大主流開發技術。

與之相隨,小程序的開發生態也在蓬勃發展,從最初的微信原生開發,到wepympvue、taro、uni-app等框架依次出現,從刀耕火種演進為現代化開發,生態越來越豐富。

選擇多了,問題也就來了,開發小程序,該用原生還是選擇三方框架?

首先,微信原生開發的槽點大多集中如下:

1. 原生開發對Node、預編譯器、webpack支持不好,影響開發效率和工程構建流程
2. 微信定義了一個不倫不類的語法,不如正經學vue、react,學會了全端通用,而不是只為微信小程序
3. vue/react生態里有太多周邊工具,可以提高開發效率,比如ide、校驗器、三方庫。。。
4. 微信那個ide和專業編輯器相比實在不好用

同時,開發者對三方框架,又總是有各種顧慮:

1. 怕性能不如原生
2. 怕有些功能框架實現不了,只能用原生
3. 怕框架不穩定,跳到坑里
4. 以及諸多三方框架,到底該用哪個

  • 面對如此糾結的場景,不少熱心開發者發布評測文章分享經驗,但感覺眾說紛紜,過期信息太多。缺少一份非常專業的、深度的,或者按如今流行的話來講,“硬核的”評測報告。

做評測報告這件事,不同于泛泛經驗分享,其實非?;ㄙM時間。它需要:

  • 你必須成為每一個框架的專業使用人員,而不是淺淺的了解一下這些框架
  • 真實的動手寫多個平臺的測試例,比較各個平臺的功能、性能,了解他們的社區情況、技術服務情況
  • 你要有長期跟蹤和更新報告的能力,避免半年后淪為過期信息

換言之:評測要想真,功夫得做深!

本文從面向用戶、面向開發者兩大維度七大細項,對微信原生及主流的wepympvuetaro、uni-app開發框架進行橫向對比,希望給開發者在小程序框架選型時提供一種參考思路。本文基于各框架官網可采集到的公開數據及真實測試數據,希望客觀公正地評價各個框架的現狀和優劣。但宥于利益相關,本文的觀點很可能是帶有偏向性的,大家可以帶著批判的眼光來看待,如發現本文中有任何評測失真,歡迎在這里報 issuse。

面向用戶、面向開發者維度,具體包括:

1. 用戶:提供完整的業務實現,并保證高性能體驗
2. 開發者:平緩的學習曲線、現代開發體驗(工程化)、高效的社區支持、活躍的開發迭代、多端復用

1. 用戶

1.1 功能實現

軟件開發,首要目標是向用戶提供完整、閉環的業務功能。

在web開發中,如果vue、react等框架的使用,造成開發者無法操作瀏覽器提供的所有api,那這樣的框架肯定是不成熟的。小程序開發也一樣,任何開發框架,都不能限制底層的api調用。

而各種業務功能底層依賴微信暴漏的組件和接口(微信官網介紹的組件和 API 規范,也即微信原生API),三方框架是基于微信原生進行的二次封裝,開發者此時常會有個疑問:小程序在不斷的迭代升級,如果某項業務依賴于最新的小程序API,但三方框架尚未封裝,該怎么辦?

實際上就像web開發的vue、react一樣,瀏覽器出了一個新API,并不會涉及vue、react的升級。本評測里的所有框架,都不會限制開發者調用底層能力。這里詳細解釋下原因:

  • wepy:未對小程序API作二次封裝,API依然使用微信原生的,框架與微信小程序是否新增API無關
  • mpvue:支持微信的所有原生組件和api,無限制。同時框架封裝了自己的跨端API,使用方式類似mpvue.request()
  • taro:支持微信的所有原生組件和api,無限制。同時框架封裝了自己的跨端API,使用方式類似Taro.request(),支持Taro 代碼與小程序代碼混寫,可通過混寫的方式調用框架尚未封裝的小程序新增API
  • uni-app:支持微信的所有原生組件和api,無限制。在跨端方面,即便仍然使用微信原生的組件和API,也可以直接跨端編譯到App、H5、以及支付寶百度頭條等小程序。但為了管理清晰,推薦使用uni封裝的API,類似uni.request()。同時支持條件編譯,可在條件編譯代碼塊中,隨意調用各個平臺新增的API及組件

注:以上順序,按各個框架的誕生順序排序,下同。

故,三方框架均可調用所有小程序API,完成用戶的業務需求,這個維度各框架是無差別的。然而有差別的,是性能體驗。

1.2 性能體驗

三方框架,內部大多做了層層封裝,這些封裝是否會增加運行負載,導致性能下降?尤其是與原生微信小程序開發相比性能怎么樣,這是大家普遍關心的問題。

為客觀的進行對比,我們特意搭建了一個測試模型,詳細如下:

開發內容:開發一個仿微博小程序首頁的復雜長列表,支持下拉刷新、上拉翻頁、點贊。

  • 界面如下:
  • 開發版本:一共開發了5個版本,包括微信原生版wepy版、mpvue版、taro版、uni-app版,按照官網指引通過cli方式默認安裝。

  • 測試代碼開源(Github倉庫地址:https://github.com/dcloudio/test-framework),
    Tips:若有同學覺得測試代碼寫法欠妥,歡迎提交 PR 或 Issus

  • 測試機型:紅米 Redmi 6 Pro、MIUI 10.2.2.0 穩定版(最新版)、微信版本 7.0.3(最新版)

  • 測試環境:每個框架開始測試前,殺掉各App進程、清空內存,保證測試機環境基本一致;每次從本地讀取靜態數據,屏蔽網絡差異。

我們以上述仿微博小程序為例,測試2個容易出性能問題的點:長列表加載、大量點贊組件的響應。

1.2.1 長列表加載

仿微博的列表是一個包含很多組件的列表,這種復雜列表對性能的壓力更大,很適合做性能測試。

從觸發上拉加載到數據更新、頁面渲染完成,需要準確計時。人眼視覺計時肯定不行,我們采用程序埋點的方式,制定了如下計時時機:

  • 計時開始時機:交互事件觸發,框架賦值之前,如:上拉加載(onReachBottom)函數開頭
  • 計時結束時機:頁面渲染完畢(微信setData回調函數開頭)

Tips:setData回調函數開頭可認為是頁面渲染完成的時間,是因為微信setData定義如下(微信規范):

測試方式:從頁面空列表開始,通過程序自動觸發上拉加載,每次新增20條列表,記錄單次耗時;固定間隔連續觸發 N 次上拉加載,使得頁面達到 20*N 條列表,計算這 N 次觸發上拉到渲染完成的平均耗時。

測試結果如下:

說明:以400條微博列表為例,從頁面空列表開始,每隔1秒觸發一次上拉加載(新增20條微博),記錄單次耗時,觸發20次后停止(頁面達到400條微博),計算這20次的平均耗時,結果微信原生在這20次 觸發上拉 -> 渲染完成 的平均耗時為876毫秒,最快的uni-app是741毫秒,最慢的mpvue是4493毫秒

大家初看這個數據,可能比較疑惑,別急,下方有詳細說明

說明1:為何 mpvue/wepy 測試數據不完整?

mpvuewepy 誕生之初,微信小程序尚不支持自定義組件,無法進行組件化開發;mpvue、wepy 為解決這個問題,將用戶編寫的Vue組件,編譯為WXML中的模板template,變相實現了組件化開發能力,提高代碼復用性,這在當時的技術條件下是很棒的技術方案。

但如此方案,在頁面復雜、組件較多的時,會大量增加頁面 dom 節點數量,甚至超出微信的 dom 節點數限制。我們在 紅米手機(Redmi 6 Pro)上實測,頁面組件超過500個時,mpvue、wepy 實現的仿微博App就會報出如下異常,并停止渲染,故這兩個測試框架在組件較多時,測試數據不完整。這也就意味著,當頁面組件太多時,無法使用這2個框架。

dom limit exceeded please check if there's any mistake you've made

Tips1:wepy官網的CHANGELOG,提到 v1.7.2 測試版本添加了對小程序原生組件的支持,實測坑很多,因為是測試版,官方在 issue 中也表示不推薦使用;按照官網文檔,默認安裝的 v1.7.3 正式版本并不支持原生組件

Tips2:wepy在400條列表以內,為何性能高于微信原生框架,這個跟自定義組件管理開銷及業務場景有關(wepy編譯為模板,不涉及組件創建及管理開銷),后續對微博點贊,涉及組件數據傳遞時,微信原生框架的性能優勢就提現出來了,詳見下方測試數據。

說明2:為什么測試數據顯示uni-app 會比微信原生框架的性能略好呢?

其實,在頁面上有200條記錄(200個組件)時,taro 性能數據也比微信原生框架更好。

微信原生框架耗時主要在setData調用上,開發者若不單獨優化,則每次都會傳遞大量數據;而 uni-apptaro 都在調用setData之前自動做diff計算,每次僅傳遞變動的數據。

例如當前頁面有20條數據,觸發上拉加載時,會新加載20條數據,此時原生框架通過如下代碼測試時,setData會傳輸40條數據

data: {
    listData: []
},
onReachBottom() { //上拉加載
    let listData = this.data.listData;
    listData.push(...Api.getNews());//新增數據
    this.setData({
        listData
    }) //全量數據,發送數據到視圖層
}

開發者使用微信原生框架,完全可以自己優化,精簡傳遞數據,比如修改如下:

data: {
    listData: []
},
onReachBottom() { //上拉加載
    // 通過長度獲取下一次渲染的索引
    let index = this.data.listData.length;
    let newData = {}; //新變更數據
    Api.getNews().forEach((item) => {
        newData['listData[' + (index++) + ']'] = item //賦值,索引遞增
    }) 
    this.setData(newData) //增量數據,發送數據到視圖層
}

經過如上優化修改后,再次測試,微信原生框架性能數據如下:

從測試結果可看出,經過開發者手動優化,微信原生框架可達到更好的性能,但 uni-app、taro 相比微信原生,性能差距并不大。

這個結果,和web開發類似,web開發也有原生js開發、vue、react框架等情況。如果不做特殊優化,原生js寫的網頁,性能經常還不如vue、react框架的性能。

也恰恰是因為Vue、react框架的優秀,性能好,開發體驗好,所以原生js開發已經逐漸減少使用了。

復雜長列表加載下一頁評測結論:微信原生開發手工優化,uni-app>微信原生開發未手工優化,taro > wepy > mpvue

Tips:有人以為uni-app和mpvue是一樣的,早期uni-app確實使用過mpvue,但后來因為性能和vue語法支持度問題已經重新開發了。

1.2.2 點贊組件響應速度

長列表中的某個組件,比如點贊組件,點擊時是否能及時的修改未贊和已贊狀態?是這項測試的評測點。

測試方式:

  • 選中某微博,點擊“點贊”按鈕,實現點贊狀態狀態切換(已贊高亮、未贊灰色),
  • 點贊按鈕 onclick函數開頭開始計時,setData回調函數開頭結束計時;

在紅米手機(Redmi 6 Pro)上進行多次測試,求其平均值,結果如下:

說明:也就是在列表數量為400時,微信原生開發的應用,點贊按鈕從點擊到狀態變化需要111毫秒。

測試結果數據說明:

  • wepy/mpvue 測試數據不完整的原因同上,在組件較多時,頁面已經不再渲染了
  • 基于微信自定義組件實現組件開發的框架(uni-app/taro),組件數據通訊性能接近于微信原生框架,遠高于基于template實現組件開發的框架(wepy/mpvue)性能

組件數據更新性能測評:微信原生開發,uni-app,taro > wepy > mpvue

綜上,本性能測試做了2個測試,長列表加載和組件狀態更新,綜合2個實驗,結論如下:
微信原生開發手工優化,uni-app>微信原生開發未手工優化,taro > wepy > mpvue

2.開發者

在滿足用戶業務需求的前提下,我們談談開發者的需求,從如下幾個維度比較:

  • 平緩的學習曲線:簡單易學,最好能復用現有技術棧,豐富的學習資料
  • 高效的開發體驗:現代前端開發流程、工程化支持
  • 高效的社區支持:遇到問題,可很快的尋求到幫助
  • 活躍的開發迭代:框架處于積極更新升級狀態,無需擔心停更

2.1 平緩的學習曲線

2.1.1 DSL語法支持

選擇開發團隊熟悉的、能快速上手的DSL,是團隊框架選型的基本點。

  • 首先微信原生的開發語法,既像React ,又像Vue,有點不倫不類,對于開發者來說,等于又要學習一套新的語法,大幅提升了學習成本,這一直被大家所詬病。

  • 其它開發框架基本都遵循React、Vue(類Vue)語法,其主要目的:復用工程師的現有技術棧,降低學習成本。此時,框架對于原框架(React/Vue)語法的支持度就是一個重要的衡量標準,如果支持度較低、和原框架語法差異較大,則開發者無異于要學習一門新的框架,成本太高。

實際開發中發現,各個開發框架,都沒有完全實現VueReact在web上的所有語法:

  • wepy開發風格接近于 Vue.js,屬于類Vue實現,相對微信原生開發算前進了一大步,但相比完整Vue語法還有較大差距,開發時需要單獨學習它的規則;

  • mpvue、uni-app 框架基于 Vue.js 核心,通過修改 Vue.jsruntimecompiler,實現了在小程序端的運行。mpvue支持的Vue語法略少,uni-app 則基本支持絕大多數vue語法,如filter、復雜 JavaScript 表達式等;

  • taro 對于 JSX 的語法支持度,也達到了絕大多數都支持的完善程度。

  • DSL語法支持評測:taro,uni-app > mpvue > wepy > 微信原生

2.1.2 學習資料完善度

官方文檔、問題搜索、示例demo的完備度方面:

  • 微信原生:文檔豐富,API搜索準確,官方有示例demo,支持官網上調起微信開發者工具,預覽運行效果 詳見
  • wepy:文檔只有2頁,沒有搜索,組件API等文檔都直接看微信的文檔。沒有提供示例demo,很多配置需要靠猜。詳見
  • mpvue:文檔較少,但其概念不復雜,組件API等文檔都直接看微信的文檔,學習難度低。問題搜索效果一般。沒有提供示例demo。詳見
  • taro:基礎文檔完整,具體使用問題資源較少,問題搜索效果一般,示例demo只包含基礎功能,僅發布了微信一端。詳見
  • uni-app:基礎文檔和各種使用專題內容豐富,問題搜索效果較好,示例demo功能完備,并發布為7端上線。詳見

教學課程方面:

學習資料完善度評測:微信原生 > uni-app > mpvue , taro > wepy

2.2 現代前端開發體驗

開發體驗層面,處于明顯劣勢的是微信原生開發,主要差距在于:

  • 框架開發提供了精簡的代碼組織(微信原生開發,一個Page由4個文件構成,寫個代碼要開的標簽卡太多)
  • 框架開發提供了更強大的組件化能力
  • 框架開發提供了應用狀態管理(類Vuex/Redux/Mobx等)
  • 框架開發能靈活支持各種 Sass 等 預處理器
  • 框架開發可提供完整的 ES Next 語法支持
  • 框架開發方便自定義構建策略

其它小程序開發框架均支持cli模式,可以在主流前端工具中開發,且基本都帶有d.ts的語法提示庫。

由于mpvue、uni-app、taro直接支持vue、react語法,配套的ide工具鏈較豐富,著色、校驗、格式化完善;wepy要弱一些,有部分三方維護的vscode插件。

好的開發工具,絕對可以大幅提升開發體驗,這個維度上,明顯高出一截的框架是uni-app,其出品公司同時也是HBuilder的出品公司,DCloud.io。HBuilder是四大主流前端開發工具(可對比百度指數,其為uni-app做了很多優化,故uni-app的開發效率、易用性非其他框架可及。

開發體驗維度,對比結果:uni-app > taro,mpvue > wepy > 微信原生

這里可以輸出一個結論:如果你需要工程化能力,那就直接忘了微信原生開發吧。

2.3 高效的社區支持

學習、開發難免遇到問題,官方技術支持和社區活躍度很重要。

本次評測demo開發期間,我們的同學(同時掌握vue和react),在學習研究各個多端框架時,切實感受到由于語法、學習資料、社區的差異帶來的學習門檻,吐出了很多槽。

綜合評估,本項評測結論:微信原生 , uni-app > taro > mpvue > wepy

2.4 活躍的開發迭代

開發者必須關心一個問題:該項目是否有人長期維護?

這個問題可以通過github commits 頻次、產品更新日志(changelog)、百度搜索指數等指標來衡量和對比。

github commits 頻次

我們采集2019年4月份(時間為4.1 ~ 4.30),每個項目在github上的master分支有commit的天數,結果如下:

Tips:

  • 微信原生是閉源的,看不到 commits 數量,但保持每月至少一次的更新節奏,詳見
  • wepy的master分支無commit,最新的2.0.x分支在4月份也僅1天有commit記錄

從 commit 的記錄來看,taro、uni-app處于更新比較活躍的狀態,wepympvue則相對疲軟,呈現無人維護之態。

產品更新日志

通過瀏覽產品更新日志,可確認產品是否在積極迭代、增加新功能、修復用戶bug。

我們分別查看各框架官方鏈接的更新日志(CHANGELOG),下方是鏈接地址:

通過產品更新日志對比,微信原生、taro、uni-app 三者更新頻繁,bug修復、新功能補充都處于比較緊湊的狀態;而mpvue、wepy則已有長時間沒有版本發布,wepy甚至有將近1年時間未發布正式版本,開發者選型需謹慎。

2.5 多端復用

隨著微信小程序的火爆,支付寶、百度、字節跳動等公司也先后進入小程序領域,這些公司個個日活過億,坐擁海量用戶,企業主希望將自己的業務觸達每個用戶,不管這個用戶在哪個小程序中。

需求轉接到程序員這里,程序員怎么辦?難道真的每個平臺到處搬磚嗎?此時,一套代碼、多端發布就成為很多程序員的夢想,小程序跨端框架應運而生。

現實真能如此理想嗎?每個跨端框架能否真的像官網宣傳的那樣,實現開發一次,發布到所有小程序平臺?甚至和H5平臺復用代碼?

我們用事實說話,依然使用上述仿微博App,依次發布到各平臺,驗證每個框架在各端的兼容性,結果如下:

測試結果說明:

  • ? 表示支持且功能正常,? 表示不支持,其它則表示支持但存在部分bug或兼容問題

通過這個簡單的例子可以看出,跨端支持度測評結論: uni-app,taro > mpvue> 原生微信小程序、wepy

但是僅有上面的測試還不全面,實際業務要比這個測試例復雜很多。但我們沒法開發很多復雜業務做評測,所以還需要再對照各家文檔補充一些信息。 由于每個框架的文檔中都描述了各種組件和API的跨端支持程度。我們過了幾家的文檔,發現各家基本是以微信小程序為基線,然后把各種組件和API在其他端實現了一遍:

  • taro:H5端實現了大部分微信的API
  • uni-app:組件、API、配置,大部分在各個端均已實現,個別API有說明在某些端不支持??梢钥闯鰑ni-app是完整在H5端實現了一套微信模擬器

跨端框架,一方面要考慮框架提供的通用api跨端支持,同時還要考慮不同端的特色差異如何兼容。畢竟每個端都會有自己的特色,不可能完全一致。

  • taro:提供了js環境變量判斷和統一接口的多端文件,可以在組件、js、文件方面擴展多端,不支持其他環節的分平臺處理。
  • uni-app:提供了條件編譯模型,所有代碼包括組件、js、css、配置json、文件、目錄,均支持條件編譯,可不受限的編寫各端差異代碼。

跨端框架,還涉及一個ui框架的跨端問題,評測結果如下:

  • taro:官方提供了taro ui,只支持微信小程序和H5兩端,不支持App,詳見
  • uni-app:官方提供了uni ui,可全端運行;uni-app還有一個插件市場,里面有很多三方ui組件,詳見

最后補充跨端案例:

  • mpvue:微信端案例豐富,未見其它端案例
  • taro:微信端案例豐富,百度、支付寶、H5端亦有少量案例
  • uni-app:多端案例豐富,官方示例已發布到7端(包括App端)

綜合以上信息,本項的最終評測結論:uni-app > taro > mpvue > 原生微信小程序、wepy

這里可以輸出一個結論,如果有多端發布需求,微信原生開發、wepy這兩種方式可以直接排除了。

結語

真實客觀的永遠是實驗和數據,而不是結論。不同需求的開發者,可以根據上述實驗數據,自行得出自己的選型結論。

但作為一篇完整的評測,我們也必須提供一份總結,雖然它可能加入了我們的主觀感受:

如果你只開發微信小程序,不做多端,那么使用uni-app、taro是更優的選擇,他們相當于web世界的vue和react,有了這些工具,不再需要使用原生wxml開發。

  • 如果堅持微信原生開發,需要注意手動寫優化代碼來控制setdata,并且注意其工程化能力非常弱
  • 如果你是react系,那就用taro
  • 如果是vue系,那就用uni-appuni-app在性能、周邊生態和開發效率上更有優勢

如果你開發多端,uni-apptaro都可以,可根據自己熟悉的技術棧選擇,相對而言uni-app的多端成熟度更高一些。

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