基于React Native的應(yīng)用熱發(fā)布實(shí)踐

1 熱發(fā)布

網(wǎng)頁發(fā)布 VS APP發(fā)布

網(wǎng)頁發(fā)布:服務(wù)端上線新的網(wǎng)頁代碼,用戶端通過鏈接直接訪問。

APP發(fā)布:?發(fā)布新的包裝包(應(yīng)用市場(chǎng):上傳新的包裝包;應(yīng)用內(nèi)升級(jí):服務(wù)端發(fā)布新的包裝包),用戶端下載,安裝。

網(wǎng)頁發(fā)布屬于熱發(fā)布,完全?受控于服務(wù)端

APP發(fā)布的限制:
應(yīng)用市場(chǎng)審核
用戶端下載,安裝

APP熱發(fā)布的目的是實(shí)現(xiàn)類似于網(wǎng)頁的發(fā)布方式,排除?更新對(duì)于應(yīng)用市場(chǎng)和用戶的依賴,完全由服務(wù)端控制。

2 APP熱發(fā)布的方式

2.1 H5熱發(fā)布

功能完全由H5實(shí)現(xiàn),APP使用WebView來加載。

優(yōu)勢(shì):完全熱發(fā)布

劣勢(shì)

  • 性能-H5的性能相比Native差得比較多,交互體驗(yàn)較差。
  • 緩存-H5的緩存受制于系統(tǒng)WebView,在無網(wǎng)或緩存過期情況下無法呈現(xiàn)界面。

2.2 數(shù)據(jù)熱發(fā)布

數(shù)據(jù)由服務(wù)端控制,動(dòng)態(tài)發(fā)布,APP根據(jù)數(shù)據(jù)來展現(xiàn)UI,實(shí)現(xiàn)UI有限的動(dòng)態(tài)性(UI動(dòng)態(tài)支持預(yù)先在APP中定義好)。

這里的數(shù)據(jù)也包括腳本數(shù)據(jù)的情況,APP通過腳本引擎執(zhí)行腳本,根據(jù)結(jié)果來執(zhí)行對(duì)應(yīng)邏輯。

優(yōu)勢(shì):數(shù)據(jù)層面熱發(fā)布

劣勢(shì):不能實(shí)現(xiàn)UI和邏輯的完全熱發(fā)布

2.3 插件化熱發(fā)布

APP的獨(dú)立功能作為插件,動(dòng)態(tài)下載,動(dòng)態(tài)運(yùn)行,插件發(fā)布由服務(wù)端動(dòng)態(tài)控制。

優(yōu)勢(shì):功能?性熱發(fā)布

劣勢(shì):使用非系統(tǒng)公開API,有失效風(fēng)險(xiǎn)

2.4 React Native

還有一種思路,APP作為基礎(chǔ)容器,應(yīng)用功能作為腳本文件,動(dòng)態(tài)下發(fā),?通過解析引擎動(dòng)態(tài)執(zhí)行,展現(xiàn)為Native UI,同時(shí)控制數(shù)據(jù)和業(yè)務(wù)邏輯。

腳本文件發(fā)布由服務(wù)端動(dòng)態(tài)控制,能夠?qū)崿F(xiàn)整個(gè)APP或者部分功能完全熱發(fā)布。

React Native是facebook開源的構(gòu)建跨平臺(tái)應(yīng)用的框架,它的原理是,通過JavascriptCore引擎,解析JSX(類似XML的Javascript擴(kuò)展語言)腳本代碼,生成Virtual DOM,再轉(zhuǎn)換為Native視圖,同時(shí)通過橋接JS和Native,實(shí)現(xiàn)事件交互。

React Native通過Virtual DOM,以diff的方式交給Native渲染,?其diff算法相當(dāng)高效,能夠保證良好的Native性能。這是它優(yōu)于H5的地方。

優(yōu)勢(shì):

  • 完全熱發(fā)布
  • 良好的Native性能
  • 跨平臺(tái)復(fù)用:Andriod, iOS, H5。
  • 大廠出品:持續(xù)維護(hù)性(兩周一個(gè)release版本);開放性,三方開源庫支持。

劣勢(shì):

  • 成熟度不夠。
  • 目前支持Android4.1和iOS7.0以上系統(tǒng)版本。

對(duì)動(dòng)態(tài)性要求較高的APP,React Native提供了一種解決方案,實(shí)現(xiàn)類似網(wǎng)頁的發(fā)布效果,同時(shí)保證良好的Native性能

使用React Native的APP:
Facebook,QQ,QQ音樂,QQ空間(發(fā)現(xiàn)Tab)

此外,Weex是阿里開源的移動(dòng)端跨平臺(tái)開發(fā)框架,原理與React Native類似,只不過它的腳本語言換成了Vue(也是JS框架)。

3 React Native原理

3.1 React Native集成

React Native(以下簡(jiǎn)稱RN)的集成參考官網(wǎng):
https://facebook.github.io/react-native/docs/getting-started.html

3.2 RN目錄結(jié)構(gòu)

RN工程目錄結(jié)構(gòu)
  • *.android.js:Android 的JS文件
  • *.ios.js:iOS的JS文件
  • android:Android的Native工程
  • ios:iOS的Native工程
  • node_modules:RN基于NodeJS的基礎(chǔ)庫。包括基本組件,以及打包腳本等等。

3.3 RN原理

?


RN架構(gòu)

Java層
Java層為應(yīng)用的入口,啟動(dòng)C++層的JS解析器,執(zhí)行JS,并通過C++傳遞的渲染指令,從而構(gòu)建Native UI等。核心邏輯在ReactCore中完成。在UI層面,ReactCore完成了對(duì)Native視圖組件的封裝,它與JS層定義的組件是一一映射的。

Java層集成眾多優(yōu)秀開源庫,圖片處理使用的是Fresco,網(wǎng)絡(luò)通信使用的是okhttp。JS層的組件會(huì)通過這些基礎(chǔ)庫來實(shí)現(xiàn)功能,如Image組件使用Fresco來加載遠(yuǎn)程圖片,fetch組件使用okhttp來進(jìn)行網(wǎng)絡(luò)請(qǐng)求。

C++層
C++層主要封裝了JavaScriptCore(Android和iOS通用的JS引擎),用來實(shí)現(xiàn)JS的解析和執(zhí)行。基于JavaScriptCore,意味著JS可以使用ES6的新特性,如class、箭頭操作符等。

Bridge?實(shí)現(xiàn)Java和 JS之間的通信。

JSLoader用來加載JS文件,包括assets目錄和本地文件。

JS層
主要實(shí)現(xiàn)UI布局和事件分發(fā),主要有以下幾個(gè)部分:

Component:JS層通JS/JSX編寫的Component來構(gòu)建Virtual DOM,Virtual DOM是DOM在內(nèi)存中的一種輕量級(jí)表達(dá)方式,可以通過不同的渲染引擎生成不同平臺(tái)下的UI。Component的存在讓計(jì)算 DOM diff 更高效,從而使得映射到Native的視圖?渲染有很好的性能。

Layout:React使用css-layout,css-layout使用JS實(shí)現(xiàn)了flexbox ,能編譯成Native代碼,最終達(dá)到跨平臺(tái)的展示目的。

Lifecycle&Data:React 組件通過內(nèi)部的 state 變量控制生命周期及事件回調(diào)。如getInitialState方法用于定義組件初始狀態(tài),后續(xù)組件可通過 state 屬性讀取該狀態(tài)。當(dāng)?調(diào)用setState 方法就修改狀態(tài)值時(shí),RN會(huì)自動(dòng)調(diào)用 render 方法,重新渲染組件。

4 Android的RN集成

Android上,應(yīng)用是通過Activity來承載的。

復(fù)雜應(yīng)用通常由多個(gè)模塊組成,每個(gè)模塊對(duì)應(yīng)一個(gè)Activity。簡(jiǎn)單來說,我們可以以Activity為模塊單元。

4.1 Activity與bundle

RN通過bundle來承載應(yīng)用。bundle包括JS腳本代碼及其引用的資源(圖片)。
在Android上,我們?yōu)槊總€(gè)Activity綁定一個(gè)bundle,來實(shí)現(xiàn)模塊的獨(dú)立管理。

Activity與bundle.png

在Native中,我們通過BaseReactActivity?來連接RN,它通過JsBundle和Component與Bundle關(guān)聯(lián)起來。

Bundle兩種形式,一個(gè)是Assets,打包在apk中一起發(fā)布;一個(gè)File,它是動(dòng)態(tài)更新下載的。在有File時(shí)使用File,沒有File時(shí)使用Assets。

Activity的注冊(cè)我們只在Manifest中定義幾個(gè)Activity模板。例如,

  • SingleTaskActivity:launch mode為SingleTask
  • StandardActivity:launch mode為Standard
  • WebViewActivity:process為單獨(dú)的web進(jìn)程

Activity跳轉(zhuǎn)時(shí),指定對(duì)應(yīng)的模板Activity,傳遞bundle信息即可。

4.2 JS

JS文件結(jié)構(gòu)(avcdemo.android.js)

import React, {Component} from 'React'; //引入React組件

import {
  AppRegistry,
  View,
  Text,
  Image
} from 'react-native';  //引入RN組件

class AVCDemo extends Component { //定義Component
  render() {  //render定義視圖結(jié)構(gòu)
    return(
      <View style={styles.full}>
        <Text style={styles.text}>Hello RN</Text>
        <Image source={require('./res/demo/kaola.png')} style={styles.img}></Image>
      </View>
    )
  }
}

var styles = {  //定義樣式
  full: {
    position: 'absolute',
    left: 0,
    top: 0,
    right: 0,
    bottom: 0,
    alignItems: 'center',
    justifyContent: 'center'
  },
  text: {
    fontSize: 80
  },
  img: {
    width: 200,
    height: 200
  }
}

AppRegistry.registerComponent('demo', () => AVCDemo); //注冊(cè)Component
demo

4.3 Native Activity

DemoActivity

public class DemoActivity extends AppReactActivity {

    @Override
    protected String getMainComponentName() {
        return "demo";
    }

    @Nullable
    @Override
    protected String getBundleAssetName() {
        return "avcdemo.android.bundle";
    }

}

可以看到Activity通過bundle最終綁定到Component。

4.4 Component

Component有幾個(gè)基本概念:props,state,render,生命周期。

props:靜態(tài)屬性,提供定制參數(shù)給調(diào)用方。如Image的source。

state:動(dòng)態(tài)屬性,內(nèi)部使用。當(dāng)通過setState方法改變時(shí),會(huì)調(diào)用render方法進(jìn)行重新渲染。比如,我們獲取網(wǎng)絡(luò)數(shù)據(jù)回來時(shí)需要改變界面,這時(shí)就需要將網(wǎng)絡(luò)數(shù)據(jù)作為一個(gè)動(dòng)態(tài)屬性,同時(shí)render方法中使用?該屬性來進(jìn)行渲染。

render:渲染方法,定義Component的視圖結(jié)構(gòu)。

與Activity類似,Component也有生命周期。

Component生命周期.png

4.5 RN組件

下面來看看RN對(duì)應(yīng)用實(shí)現(xiàn)的支持。首先是組件。

實(shí)現(xiàn)應(yīng)用的組件大致分為4個(gè)層面:

  • UI
  • 網(wǎng)絡(luò)
  • 存儲(chǔ)
  • 線程

4.5.1 UI

UI層面又可以細(xì)分為:UI組件,動(dòng)畫,交互事件。

UI組件
RN提供了較為豐富的基礎(chǔ)組件,以及部分復(fù)雜組件。

RN UI組件

UI組件本質(zhì)上會(huì)做一個(gè)到Native組件的映射。

RN UI組件 Android UI組件
View -> ViewGroup
Image -> ImageView
Text -> TextView
TextInput -> EditText
ViewPagerAndroid -> ViewPager
WebView -> WebView
ScrollView -> ScrollView
ListView -> ScrollView

RN的ListView并沒有采用Native的ListView,而是基于RN的ScrollView,在js層來處理ListView的邏輯。

動(dòng)畫
RN提供了兩種動(dòng)畫方式:Animated和LayoutAnimation。
Animated與Android的屬性動(dòng)畫類似,可以實(shí)現(xiàn)透明度,縮放和位移等效果。
LayoutAnimation與Android LayoutAnimation類似,作用于?加入和移除視圖樹。

交互事件
交互事件主要有兩種:點(diǎn)擊和Touch,按鍵。
RN提供Touchablexxx(TouchableOpacityTouchableHighlight等)系列組件來實(shí)現(xiàn)點(diǎn)擊、長按、滑動(dòng)交互。

onPressIn:點(diǎn)擊開始;
onPressOut:點(diǎn)擊結(jié)束或者離開;
onPress:?jiǎn)螕羰录卣{(diào);
onLongPress:長按事件回調(diào)。

事件攔截(類似于Android的onInterceptTouchEvent)
onStartShouldSetResponder
onMoveShouldSetResponder

按鍵處理,RN提供了Andorid的back鍵處理BackAndroid

4.5.2 網(wǎng)絡(luò)

RN提供fetch API用于網(wǎng)絡(luò)請(qǐng)求,它本質(zhì)是基于OkHttp實(shí)現(xiàn)。

它支持GET,POST等基本方法,包括header的傳遞,以及響應(yīng)json格式化。

另外,它也提供XMLHttpRequest和WebSocket的支持。

4.5.3 存儲(chǔ)

RN提供了簡(jiǎn)單的持久存儲(chǔ)組件AsyncStorage

它支持key-value存儲(chǔ),效果類似于Android的SharedPreference,實(shí)際上它是存儲(chǔ)在本地的sqlite數(shù)據(jù)庫中。

如果需要傳統(tǒng)的sqlite存儲(chǔ),需要自己實(shí)現(xiàn)。會(huì)有一些開源組件供實(shí)現(xiàn)參考:https://github.com/jbrodriguez/react-native-android-sqlite

4.5.4 線程

RN的應(yīng)用邏輯是運(yùn)行JS線程上的,獨(dú)立于Android的UI線程。JS線程上的更新批量傳遞給Native作UI更新。

RN提供Timers來實(shí)現(xiàn)異步邏輯。 可以通過JS本身的異步接口來實(shí)現(xiàn)(async/await)。

4.6 RN擴(kuò)展

RN官方提供的組件能夠滿足基本業(yè)務(wù)需求,如果要實(shí)現(xiàn)復(fù)雜應(yīng)用,需要進(jìn)行擴(kuò)展。

目前很多RN開源組件:https://github.com/jondot/awesome-react-native

另外,也可以自己定制。定制分為幾個(gè)方面:

  • JS調(diào)用Native
  • 定制JS層組件
  • 使用Native UI組件

4.6.1 JS調(diào)用Native

當(dāng)JS層無法滿足需求時(shí),通過需要Native層支持提供接口,來供JS層調(diào)用。RN提供Native Modules的方式來支持。

簡(jiǎn)單來說,就是Native按照規(guī)則定義好接口,同時(shí)注冊(cè)到RN中,JS層直接調(diào)用即可。

顯然,這種方式定義的Native Module不能動(dòng)態(tài)發(fā)布,它需要固化在APP中。

4.6.2 定制?JS層組件

Component組件
以ImageText為例(ImageText.js)

'use strict';

import React, {Component} from 'React';
import {
  View,
  Image,
  Text,
} from 'react-native';

class ImageText extends Component {

  props: {
    imgUrl?: string,
    text?: string,
  }

  render() {
    return(
      <View style={styles.container}>
        <Image style={styles.img} source={{uri: this.props.imgUrl}}></Image>
        <Text style={styles.text}>{this.props.text}</Text>
      </View>
    )
  }
}

var styles = {
  container: {
    flexDirection: 'row',
    marginRight: 8,
  },
  img: {
    width: 14,
    height: 14,
  },
  text: {

  },
}

module.exports = ImageText;

?然后將Component輸出:

module.exports = ImageText;

方法組件
以網(wǎng)絡(luò)請(qǐng)求為例,網(wǎng)絡(luò)請(qǐng)求通常會(huì)加上一些能用參數(shù)。可以定義一個(gè)網(wǎng)絡(luò)請(qǐng)求組件(Requestor.js)。

'use strict';

import HOST from './Host';

function get(url, headers) {
  if (headers == null) {
    headers = {};
  }
  headers[HOST.API_VERSION_KEY] = HOST.API_VERSION_VALUE;
  console.log("headers: " + JSON.stringify(headers));
  return fetch(url, {
    headers: headers
  })
}

module.exports = {get};

需要將方法組件輸出:

module.exports = {get};

常量組件

'use strict';

var apiVersion = 200;

module.exports = {
  HOST: "http://api.kkmoving.com",
  API_VERSION_KEY: "apiVersion",
  API_VERSION_VALUE: apiVersion
};

4.6.3 使用Native UI組件

Native UI組件定義參考Native UI Components

簡(jiǎn)單來說,就是定義好Native UI組件,然后通過ViewManager注冊(cè)到RN中,同時(shí)在JS層定義Component,關(guān)聯(lián)到Native UI組件。然后,這個(gè)Component就可以使用。

?需要注意的是,如果Native UI組件要求自定義大小,需要額外實(shí)現(xiàn)LayoutShadowNode并關(guān)聯(lián)到ViewManager,LayoutShadowNode提供MeasureFunction回調(diào)來實(shí)現(xiàn)組件的丈量。具體實(shí)現(xiàn)可以參考RN的Text組件實(shí)現(xiàn)(Native 代碼:ReactTextViewManager,ReactTextView,ReactTextShadowNode)。

4.7 RN工程打包

RN打包分為兩個(gè)部分,一個(gè)是bundle打包,一個(gè)是APP打包。

bundle打包,是指bundle的JS文件和圖片資源打包為獨(dú)立的文件,?作為更新包供遠(yuǎn)程下載。這是動(dòng)態(tài)bundle。

bundle打包命令:

react-native bundle --platform android --dev false \
--entry-file xxx.android.js \
--bundle-output xxx.android.bundle \
--assets-dest xxx

APP打包,首先執(zhí)行bundle打包,將生成的靜態(tài)bundle跟隨app包一起發(fā)布。保證無網(wǎng)時(shí)能夠展現(xiàn)應(yīng)用基本功能。

在Android上,跟隨打包會(huì)將JS文件打包到assets目錄中,同時(shí)將圖片資源打包到drawable目錄中。

RN打包Android的方式是通過gradle,在正常apk打包過程之前,會(huì)編譯RN的bundle。但默認(rèn)只能打包一個(gè)bundle,如果需要支持打包多個(gè)bundle,需要修改react.gradle文件(node_modules/react-native/react.gradle)。

RN在開發(fā)調(diào)試比較方便,通過react-native run-android運(yùn)行應(yīng)用,JS文件編輯后,可以直接在應(yīng)用上reload來實(shí)現(xiàn)更新,不需要重新安裝APP,類似網(wǎng)頁直接刷新的效果。

4.8 熱發(fā)布實(shí)現(xiàn)

RN熱發(fā)布的策略相對(duì)簡(jiǎn)單。

在APP端,初始發(fā)布APP時(shí),自帶靜態(tài)bundle,并每個(gè)bundle維護(hù)一個(gè)版本號(hào)。
應(yīng)用在適當(dāng)?shù)臅r(shí)機(jī),檢查bundle是否需要更新。如果有更新,則下載動(dòng)態(tài)bundle。
?應(yīng)用優(yōu)先加載動(dòng)態(tài)bundle,如無動(dòng)態(tài)bundle剛加載靜態(tài)bundle。

在服務(wù)端,?提供動(dòng)態(tài)bundle的發(fā)布,版本維護(hù),更新檢測(cè)和下載。

這是最簡(jiǎn)單的策略,當(dāng)然要做得精細(xì),還需要考慮差量更新,bundle拆包(后面會(huì)講)。

5 ?RN實(shí)踐之商品詳情頁

商品詳情頁

界面實(shí)現(xiàn)Demo

  • ScrollView
  • ViewPager
  • 帶樣式的Text
  • 遠(yuǎn)程加載的Image
  • 浮層
  • 動(dòng)畫
  • 地址選擇
  • RN WebView

在線更新Demo

  • 檢查更新
  • 下載/解壓
  • 應(yīng)用更新

6 踩過的坑

6.1 混淆設(shè)置

在RN中如果要使用Proguard,需要做兩個(gè)設(shè)置:

  • 在build.gradle中設(shè)置:

def enableProguardInReleaseBuilds = true

  • 在proguard.pro中,基于RN官方Proguard模板,另外設(shè)置:

-keep class com.facebook.** { *; }

這一點(diǎn)比較坑,官方文檔和各種模板中都沒有提到。如果不加一句,release運(yùn)行時(shí)會(huì)直接crash。

6.2 Android Studio設(shè)置

  • gradle.properties不能設(shè)置org.gradle.configureondemand=true

具體原因未知

7 待解決的問題

  • RN基礎(chǔ)庫較大(6M)。
  • Bundle文件過大(基礎(chǔ)Bundle 500k左右)。Bundle拆包,將RN庫的JS拆離到單獨(dú)的基礎(chǔ)Bundle。
  • 復(fù)雜組件的JS實(shí)現(xiàn)。
  • 性能分析和優(yōu)化。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,818評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,185評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,656評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,647評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,446評(píng)論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,951評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,041評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,189評(píng)論 0 287
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,718評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,602評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,800評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,045評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,419評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評(píng)論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,420評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,755評(píng)論 2 371

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