【Hybrid開發(fā)高級系列】ReactNative(六) —— ReactNative開發(fā)技巧總結(jié)

1 React基礎(chǔ)

1.1 環(huán)境準(zhǔn)備

1.1.1 cnmp使用

1.1.1.1 cnmp安裝

????????你可以使用我們定制的 cnpm(gzip壓縮支持) 命令行工具代替默認(rèn)的 npm:

$ npm install -g cnpm

--registry=https://registry.npm.taobao.org

????????或者你直接通過添加 npm 參數(shù) alias 一個新命令:

alias cnpm="npm --registry=https://registry.npm.taobao.org\

--cache=$HOME/.npm/.cache/cnpm \

--disturl=https://npm.taobao.org/dist \

--userconfig=$HOME/.cnpmrc"


# Or alias it in .bashrc or .zshrc

$ echo '\n#alias for cnpm\nalias cnpm="npm--registry=https://registry.npm.taobao.org \

?--cache=$HOME/.npm/.cache/cnpm \

?--disturl=https://npm.taobao.org/dist \

? --userconfig=$HOME/.cnpmrc"' >>

~/.zshrc && source ~/.zshrc

1.1.1.2 安裝模塊

????????從 registry.npm.taobao.org安裝所有模塊. 當(dāng)安裝的時候發(fā)現(xiàn)安裝的模塊還沒有同步過來, 淘寶 NPM 會自動在后臺進(jìn)行同步, 并且會讓你從官方NPMregistry.npmjs.org進(jìn)行安裝. 下次你再安裝這個模塊的時候, 就會直接從 淘寶 NPM 安裝了.

$ cnpm install [name]

1.2 運行機理

1.2.1 render渲染方法

????????ReactDOM.render渲染方法是React的最基本方法,用于將模板轉(zhuǎn)為 HTML 語言遥金,并插入指定的 DOM 節(jié)點柄粹。

ReactDOM.render(

????<h1>Hello, world!</h1>,?

????document.getElementById('example')

);

????????上面代碼將一個 h1 標(biāo)題,插入 example 節(jié)點(查看 demo01)沧卢,運行結(jié)果如下咸包。

1.2.2 組件(component)

????????React允許將代碼封裝成組件(component)翰意,然后像插入普通 HTML 標(biāo)簽一樣战惊,在網(wǎng)頁中插入這個組件。React.createClass 方法就用于生成一個組件類(查看 demo04)但两。

var HelloMessage = React.createClass({

? render: function() {

? ? ? return <h1>Hello {this.props.name}</h1>;

? }

});


ReactDOM.render(

????<HelloMessage name="John" />? ,

? ? document.getElementById('example')

);

????????上面代碼中鬓梅,變量 HelloMessage 就是一個組件類。模板插入<HelloMessage />? 時谨湘,會自動生成 HelloMessage 的一個實例(下文的"組件"都指組件類的實例)绽快。所有組件類都必須有自己的 render 方法,用于輸出組件紧阔。

????????注意坊罢,組件類的第一個字母必須大寫,否則會報錯擅耽,比如HelloMessage不能寫成helloMessage活孩。另外,組件類只能包含一個頂層標(biāo)簽乖仇,否則也會報錯憾儒。

????????組件的用法與原生的 HTML 標(biāo)簽完全一致,可以任意加入屬性乃沙,比如<HelloMessage name="John" >起趾,就是 HelloMessage 組件加入一個 name 屬性,值為 John警儒。組件的屬性可以在組件類的 this.props 對象上獲取训裆,比如 name 屬性就可以通過 this.props.name 讀取。上面代碼的運行結(jié)果如下蜀铲。

????????添加組件屬性边琉,有一個地方需要注意,就是 class 屬性需要寫成 className 蝙茶,for 屬性需要寫成 htmlFor 艺骂,這是因為 class 和 for 是 JavaScript 的保留字。

1.2.3 this.props.children

????????this.props 對象的屬性與組件的屬性一一對應(yīng)隆夯,但是有一個例外钳恕,就是 this.props.children 屬性。它表示組件的所有子節(jié)點(查看 demo05)蹄衷。

var NotesList = React.createClass({

? render: function() {

??? return (

????????<ol>

? ? ? ? {

??????? ????React.Children.map(this.props.children, function (child) {

? ? ? ? ? ? ? ? return <li>{child}</li>;

??????? ????})

????? }

????????</ol>

??? );

? }

});


ReactDOM.render(

????<NotesList>

? ? ????<span>hello</span>

? ? ? ? <span>world</span>

????</NotesList>,

? ? document.body

);

????????上面代碼的 NoteList 組件有兩個 span 子節(jié)點忧额,它們都可以通過 this.props.children 讀取,運行結(jié)果如下愧口。

????????這里需要注意睦番, this.props.children 的值有三種可能:如果當(dāng)前組件沒有子節(jié)點,它就是 undefined ;如果有一個子節(jié)點,數(shù)據(jù)類型是 object 托嚣;如果有多個子節(jié)點巩检,數(shù)據(jù)類型就是 array 。所以示启,處理 this.props.children 的時候要小心兢哭。

????????React 提供一個工具方法 React.Children來處理 this.props.children 。我們可以用 React.Children.map 來遍歷子節(jié)點夫嗓,而不用擔(dān)心 this.props.children 的數(shù)據(jù)類型是 undefined 還是 object迟螺。更多的 React.Children 的方法,請參考官方文檔舍咖。

1.2.4 PropTypes

????????組件的屬性可以接受任意值矩父,字符串、對象排霉、函數(shù)等等都可以窍株。有時,我們需要一種機制郑诺,驗證別人使用組件時夹姥,提供的參數(shù)是否符合要求杉武。

????????組件類的PropTypes屬性辙诞,就是用來驗證組件實例的屬性是否符合要求(查看 demo06)。

var MyTitle = React.createClass({

? propTypes: {

??? title: React.PropTypes.string.isRequired,

? },


? render: function() {

???? return

????????<h1>{this.props.title}</h1>;

?? }

});

????????上面的Mytitle組件有一個title屬性轻抱。PropTypes 告訴 React飞涂,這個 title 屬性是必須的,而且它的值必須是字符串∑硭眩現(xiàn)在较店,我們設(shè)置 title 屬性的值是一個數(shù)值。

var data = 123;


ReactDOM.render(

????<MyTitle title={data} />,

? ? document.body

);

????????這樣一來容燕,title屬性就通不過驗證了梁呈。控制臺會顯示一行錯誤信息蘸秘。

Warning: Failed propType: Invalid prop `title` of type `number` supplied to `MyTitle`, expected `string`.

????????更多的PropTypes設(shè)置官卡,可以查看官方文檔

????????此外醋虏,getDefaultProps 方法可以用來設(shè)置組件屬性的默認(rèn)值寻咒。

var MyTitle = React.createClass({

? getDefaultProps: function () {

??? return {

????? title: 'Hello World'

??? };

? },


? render: function() {

???? return

????????<h1>{this.props.title}</h1>;

?? }

});


ReactDOM.render(

????<MyTitle />,

? ? document.body

);

????????上面代碼會輸出"Hello World"。

1.2.5 獲取真實的DOM節(jié)點

????????組件并不是真實的 DOM 節(jié)點颈嚼,而是存在于內(nèi)存之中的一種數(shù)據(jù)結(jié)構(gòu)毛秘,叫做虛擬 DOM (virtual DOM)。只有當(dāng)它插入文檔以后,才會變成真實的 DOM 叫挟。根據(jù) React 的設(shè)計艰匙,所有的 DOM 變動,都先在虛擬 DOM 上發(fā)生抹恳,然后再將實際發(fā)生變動的部分旬薯,反映在真實 DOM上,這種算法叫做 DOM?diff适秩,它可以極大提高網(wǎng)頁的性能表現(xiàn)绊序。

????????但是,有時需要從組件獲取真實 DOM 的節(jié)點秽荞,這時就要用到 ref 屬性(查看 demo07)骤公。

var MyComponent = React.createClass({

? handleClick: function() {

??? this.refs.myTextInput.focus();

? },

? render: function() {

??? return (

????????<div>

? ? ????????<input type="text" ref="myTextInput" />

????????????<input type="button" value="Focus the text input" onClick={this.handleClick} />

????????</div>

??? );

? }

});


ReactDOM.render(

????<MyComponent />,

? ? document.getElementById('example')

);

????????上面代碼中,組件 MyComponent 的子節(jié)點有一個文本輸入框扬跋,用于獲取用戶的輸入阶捆。這時就必須獲取真實的 DOM 節(jié)點,虛擬 DOM 是拿不到用戶輸入的钦听。為了做到這一點洒试,文本輸入框必須有一個 ref 屬性,然后 this.refs.[refName] 就會返回這個真實的 DOM 節(jié)點朴上。

????????需要注意的是垒棋,由于 this.refs.[refName] 屬性獲取的是真實 DOM ,所以必須等到虛擬 DOM 插入文檔以后痪宰,才能使用這個屬性叼架,否則會報錯。上面代碼中衣撬,通過為組件指定 Click 事件的回調(diào)函數(shù)乖订,確保了只有等到真實 DOM 發(fā)生 Click 事件之后,才會讀取 this.refs.[refName] 屬性具练。

????????React 組件支持很多事件乍构,除了 Click 事件以外,還有 KeyDown 扛点、Copy哥遮、Scroll 等,完整的事件清單請查看官方文檔占键。

1.2.6 this.state

????????組件免不了要與用戶互動昔善,React 的一大創(chuàng)新,就是將組件看成是一個狀態(tài)機畔乙,一開始有一個初始狀態(tài)君仆,然后用戶互動,導(dǎo)致狀態(tài)變化,從而觸發(fā)重新渲染 UI (查看 demo08)返咱。

var LikeButton = React.createClass({

? getInitialState: function() {

??? return {liked: false};

? },

? handleClick: function(event) {

??? this.setState({liked: !this.state.liked});

? },

? render: function() {

??? var text = this.state.liked ? 'like' : 'haven\'t liked';

??? return (

????????<p onClick={this.handleClick}>

??????? ????You{text}this. Click to toggle.

????????</p>

??? );

? }

});


ReactDOM.render(

????<LikeButton />,

? ? document.getElementById('example')

);

????????上面代碼是一個 LikeButton 組件钥庇,它的 getInitialState 方法用于定義初始狀態(tài),也就是一個對象咖摹,這個對象可以通過 this.state 屬性讀取评姨。當(dāng)用戶點擊組件,導(dǎo)致狀態(tài)變化萤晴,this.setState 方法就修改狀態(tài)值吐句,每次修改以后,自動調(diào)用 this.render 方法店读,再次渲染組件嗦枢。

????????由于 this.props 和 this.state 都用于描述組件的特性,可能會產(chǎn)生混淆屯断。一個簡單的區(qū)分方法是文虏,this.props 表示那些一旦定義,就不再改變的特性殖演,而 this.state 是會隨著用戶互動而產(chǎn)生變化的特性氧秘。

1.2.7 表單數(shù)據(jù)讀取

????????用戶在表單填入的內(nèi)容,屬于用戶跟組件的互動趴久,所以不能用 this.props 讀韧柘唷(查看 demo9)。

var Input = React.createClass({

? getInitialState: function() {

??? return {value: 'Hello!'};

? },

? handleChange: function(event) {

??? this.setState({value: event.target.value});

? },

? render: function () {

??? var value = this.state.value;

??? return (

????????<div>

????????????<input type="text" value={value} onChange={this.handleChange} />

????????????<p>{value}</p>

? ? ? ? </div>

??? );

? }

});

ReactDOM.render(<Input />,document.body);

????????上面代碼中朋鞍,文本輸入框的值已添,不能用 this.props.value 讀取,而要定義一個 onChange 事件的回調(diào)函數(shù)滥酥,通過 event.target.value 讀取用戶輸入的值。textarea 元素畦幢、select元素坎吻、radio元素都屬于這種情況,更多介紹請參考官方文檔宇葱。

1.2.8 組件的生命周期

????????組件的生命周期分成三個狀態(tài):

???? Mounting:已插入真實DOM

???? Updating:正在被重新渲染

???? Unmounting:已移出真實DOM

????????React 為每個狀態(tài)都提供了兩種處理函數(shù)瘦真,will 函數(shù)在進(jìn)入狀態(tài)之前調(diào)用,did 函數(shù)在進(jìn)入狀態(tài)之后調(diào)用黍瞧,三種狀態(tài)共計五種處理函數(shù)诸尽。

???? componentWillMount()

???? componentDidMount()

???? componentWillUpdate(object nextProps, object nextState)

???? componentDidUpdate(object prevProps, object prevState)

???? componentWillUnmount()

????????此外,React 還提供兩種特殊狀態(tài)的處理函數(shù)印颤。

????componentWillReceiveProps(object nextProps):已加載組件收到新的參數(shù)時調(diào)用

???? shouldComponentUpdate(object nextProps, object nextState):組件判斷是否重新渲染時調(diào)用

????????這些方法的詳細(xì)說明您机,可以參考官方文檔。下面是一個例子(查看 demo10)。

var Hello = React.createClass({

? getInitialState: function () {

??? return {

????? opacity: 1.0

??? };

? },


? componentDidMount: function () {

??? this.timer = setInterval(function () {

????? var opacity = this.state.opacity;

????? opacity-= .05;

????? if (opacity< 0.1) {

??????? opacity= 1.0;

????? }

????? this.setState({

??????? opacity: opacity

????? });

??? }.bind(this), 100);

? },


? render: function () {

??? return (

????????<div style={{opacity: this.state.opacity}}>

??????? ????Hello{this.props.name}

????????</div>

??? );

? }

});


ReactDOM.render(

????<Hello name="world" />,

? ? document.body

);

????????上面代碼在hello組件加載以后际看,通過 componentDidMount 方法設(shè)置一個定時器咸产,每隔100毫秒,就重新設(shè)置組件的透明度仲闽,從而引發(fā)重新渲染脑溢。

????????另外,組件的style屬性的設(shè)置方式也值得注意赖欣,不能寫成

style="opacity:{this.state.opacity};"

????????而要寫成

style={{opacity: this.state.opacity}}

????????這是因為 React 組件樣式是一個對象屑彻,所以第一重大括號表示這是 JavaScript 語法,第二重大括號表示樣式對象顶吮。

1.3 組件引用


1.4 工程構(gòu)建

1.4.1 安裝Node.js酱酬、RN

(一) 安裝命令行工具(只需要執(zhí)行一次,之后就可以直接從下面的第二部開始):

? sudo npm install react-native-cli -g

????查看安裝的版本:npm -v

1.4.2 利用RN命令創(chuàng)建工程

?? react-native initHelloWorld //創(chuàng)建一個HelloWorld工程

1.4.3 運行項目

???1. 找到創(chuàng)建的HelloWorld項目,雙擊HelloWorld.xcodeproj即可在xcode中打開項目云矫。xcodeproj是xcode的項目文件膳沽。

? ?2.使用終端命令運行項目:?

????????cd 該項目文件夾??

? ? ? ? react-native run-ios

? ?3.在WebStorm中運行,點擊右下角的圖標(biāo)让禀,選擇Terminal挑社,輸入react-nativerun-ios即可運行⊙沧幔或輸入npm start在模擬器打開的情況下運行痛阻。

2 開發(fā)技巧

2.1 樣式

2.1.1 聲明樣式

????????在React Native中聲明樣式的方法如下:

var styles = StyleSheet.create({

? base: {

? ? width: 38,

? ? height: 38,

? },

? background: {

? ? backgroundColor: '#222222',

? },

? active: {

? ? borderWidth: 2,

? ? borderColor: '#00ff00',

? },

});

2.1.2 使用樣式

????????所有的核心組件接受樣式屬性。

<Text style={styles.base} />

<View style={styles.background} />

????????它們也接受一系列的樣式腮敌。

<View style={[styles.base, styles.background]} />

????????行為與 Object.assign 相同:在沖突值的情況下阱当,從最右邊元素的值將會優(yōu)先,并且falsy值如 false 糜工, un defined 和 null 將被忽略弊添。一個常見的模式是基于某些條件有條件地添加一個樣式。

<View style={[styles.base, this.state.active && styles.active]} />

2.1.3 樣式傳遞

????????為了讓一個call site定制你的子組件的樣式捌木,你可以通過樣式傳遞油坝。使用View.propTypes.style 和 Text.propTypes.style ,以確保只有樣式被傳遞了刨裆。

var List = React.createClass({

? propTypes: {

??? style: View.propTypes.style,

??? elementStyle: View.propTypes.style,

? },

? render: function() {

??? return (

????????<View style={this.props.style}>

??????????? {elements.map((element) =>

????????????????<View style={[styles.element, this.props.elementStyle]} />

? ? ? ? ? ? )}

? ? ? ? ?</View>);

? }?

});

// ... in another file ...

2.2 手勢應(yīng)答系統(tǒng)

觸摸應(yīng)答系統(tǒng)在 ResponderEventPlugin.js中實現(xiàn)了澈圈。

2.2.1 TouchableHighlight和Touchable*

????????應(yīng)答系統(tǒng)在使用時可能是復(fù)雜的。所以我們?yōu)閼?yīng)該“可以輕擊的”東西提供了一個抽象的Touchable實現(xiàn)帆啃。這 使用了應(yīng)答系統(tǒng)瞬女,并且使你以聲明的方式可以輕松地識別輕擊交互。在網(wǎng)絡(luò)中任何你會用到按鈕或鏈接的地方使用TouchableHighlight努潘。

2.2.2 應(yīng)答器生命周期

? ??????是否接受觸摸事件:通過實施正確的處理方法诽偷,視圖可以成為接觸應(yīng)答器坤学。有兩種方法來詢問視圖是否想成為應(yīng)答器:

????? View.props.onStartShouldSetResponder:(evt) => true,——這個視圖是否在觸摸開始時想成為應(yīng)答器?

????? View.props.onMoveShouldSetResponder: (evt)=> true,——當(dāng)視圖不是應(yīng)答器時,該指令被在視圖上移動的;

? ??????觸摸調(diào)用:這個視圖想“聲明”觸摸響應(yīng)嗎?如果視圖返回true并且想成為應(yīng)答器渤刃,那么下述的一種情況就會發(fā)生:

????????View.props.onResponderGrant:(evt)=> { }——視圖現(xiàn)在正在響應(yīng)觸摸事件拥峦。這個時候要高亮標(biāo)明并顯示 給用戶正在發(fā)生的事情卖子。

????? View.props.onResponderReject:(evt)= > { }——其他的東西是應(yīng)答器并且不會釋放它。 如果視圖正在響應(yīng)玄柠,那么可以調(diào)用以下處理程序:

????? View.props.onResponderMove:(evt)= > { }——用戶正移動他們的手指;

????? View.props.onResponderRelease:(evt)= > { }——在觸摸最后被引發(fā)诫舅,即“touchUp”羽利;

????? View.props.onResponderTerminationRequest:(evt)= >true——其他的東西想成為應(yīng)答器刊懈。這種視圖應(yīng)該釋放應(yīng)答嗎?返回true就是允許釋放;

????? View.props.onResponderTerminate:(evt)= > { }——應(yīng)答器已經(jīng)從視圖獲取了虚汛∝依耍可能在調(diào)用onResponderTerminationRequest之后被其他視圖獲取,也可能是被操作系統(tǒng)在沒有請求的情況下獲取了(發(fā)生在iOS的control center/notificationcenter)蛋辈;


????????evt是一個綜合的觸摸事件将谊,有以下形式:

????? nativeEvent

????? changedTouches——自從上個事件之后,所有發(fā)生改變的觸摸事件的數(shù)組

????? identifier——觸摸的ID

????? locationX——觸摸相對于元素的X位置

????? locationY——觸摸相對于元素的Y位置

????? pageX——觸摸相對于屏幕的X位置

????? pageY——觸摸相對于屏幕的Y位置

????? target——接收觸摸事件的元素的節(jié)點id

????? timestamp——觸摸的時間標(biāo)識符逞频,用于速度計算

????? touches——所有當(dāng)前在屏幕上觸摸的數(shù)組


? ??捕捉ShouldSet處理程序

??? ????在冒泡模式眠砾,即最深的節(jié)點最先被調(diào)用,的情況下,onStartShouldSetResponder和 onMoveShouldSetResponder 被調(diào)用励堡。這意味著,當(dāng)多個視圖為 *ShouldSetResponder 處理程序返回true時刨疼,最深的組件會成為應(yīng)答 器。在大多數(shù)情況下亭畜,這是可取的迎卤,因為它確保了所有控件和按鈕是可用的。

????????然而劲藐,有時父組件會想要確保它成為應(yīng)答器樟凄。這可以通過使用捕獲階段進(jìn)行處理。在應(yīng)答系統(tǒng)從最深的組件冒泡時汰现,它將進(jìn)行一個捕獲階段叔壤,引發(fā) * ShouldSetResponderCapture 。所以如果一個父視圖要防止子視圖在觸摸開始時成為應(yīng)答器企软,它應(yīng)該有一個 onStartShouldSetResponderCapture 處理程序饭望,返回true铅辞。

View.props.onStartShouldSetResponderCapture: (evt) => true,

View.props.onMoveShouldSetResponderCapture: (evt) => true,


? ??PanResponder

????????更高級的手勢解釋,看看 PanResponder苇倡。

2.3 調(diào)用Native模塊(iOS)

2.3.1 iOS日歷模塊的例子

????????本指南將使用 iOS日歷API的例子囤踩。假設(shè)我們希望能夠從JavaScript訪問iOS日歷。

????????Native模塊只是一個Objectve-C類综慎,實現(xiàn)了 RCTBridgeModule 協(xié)議勤庐。如果你想知道,RCT是ReaCT的一個 簡稱米罚。

// CalendarManager.h

#import "RCTBridgeModule.h"

#import "RCTLog.h"

@interfaceCalendarManager : NSObject

@end

????????React Native不會向JavaScript公開任何 CalendarManager 方法录择,除非有明確的要求。幸運的是有了RCT_EXPORT 辨宠,這會非常簡單:

// CalendarManager.m

@implementation CalendarManager

-(void)addEventWithName: (NSString *)name location: (NSString *)location

{

????? RCT_EXPORT();

????? RCTLogInfo(@"Pretending to create an event %@ at %@", name, location);

}

@end

????????現(xiàn)在從你的JavaScript文件中货裹,你可以像這樣調(diào)用方法:

???? var CalendarManager = require('NativeModules').CalendarManager;

???? CalendarManager.addEventWithName('BirthdayParty', '4 Privet Drive, Surrey');

????????注意,導(dǎo)出的方法名稱是從Objective-C選擇器的第一部分中生成的赋兵。有時它會產(chǎn)生一個非慣用的JavaScript名稱(就像在我們的例子中的那個)搔预。你可以通過為 RCT_EXPORT 提供一個可選參數(shù)更改名字拯田,如dEvent) 。

????????方法返回的類型應(yīng)該是 void 吭产。React Native橋是異步的,所以向JavaScript傳遞結(jié)果的唯一方法是使用回調(diào) 或emitting事件(見下文)鸭轮。

3 常見問題

3.1 配置類問題

3.1.1 Can not find module 'invariant'

????????解決方案:

npm install invariant -g

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末窃爷,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子医吊,更是在濱河造成了極大的恐慌逮京,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,744評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件御吞,死亡現(xiàn)場離奇詭異陶珠,居然都是意外死亡享钞,警方通過查閱死者的電腦和手機住诸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評論 3 392
  • 文/潘曉璐 我一進(jìn)店門狐肢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來份名,“玉大人,你說我怎么就攤上這事鲤孵〕饺纾” “怎么了?”我有些...
    開封第一講書人閱讀 163,105評論 0 353
  • 文/不壞的土叔 我叫張陵凯正,是天一觀的道長呕童。 經(jīng)常有香客問我夺饲,道長,這世上最難降的妖魔是什么擂找? 我笑而不...
    開封第一講書人閱讀 58,242評論 1 292
  • 正文 為了忘掉前任浩销,我火速辦了婚禮慢洋,結(jié)果婚禮上陆盘,老公的妹妹穿的比我還像新娘败明。我一直安慰自己,他們只是感情好酸员,可當(dāng)我...
    茶點故事閱讀 67,269評論 6 389
  • 文/花漫 我一把揭開白布幔嗦。 她就那樣靜靜地躺著沥潭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪呼渣。 梳的紋絲不亂的頭發(fā)上寞埠,一...
    開封第一講書人閱讀 51,215評論 1 299
  • 那天仁连,我揣著相機與錄音,去河邊找鬼使鹅。 笑死昌抠,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的裁厅。 我是一名探鬼主播侨艾,決...
    沈念sama閱讀 40,096評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼唠梨,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了茬故?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,939評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎徘跪,沒想到半個月后垮庐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,354評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,573評論 2 333
  • 正文 我和宋清朗相戀三年溉奕,在試婚紗的時候發(fā)現(xiàn)自己被綠了忍啤。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片同波。...
    茶點故事閱讀 39,745評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡戴尸,死狀恐怖冤狡,靈堂內(nèi)的尸體忽然破棺而出筒溃,到底是詐尸還是另有隱情,我是刑警寧澤浑测,帶...
    沈念sama閱讀 35,448評論 5 344
  • 正文 年R本政府宣布迁央,位于F島的核電站讹语,受9級特大地震影響顽决,放射性物質(zhì)發(fā)生泄漏才菠。R本人自食惡果不足惜赋访,卻給世界環(huán)境...
    茶點故事閱讀 41,048評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧国葬,春花似錦接奈、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽腌巾。三九已至吓坚,卻和暖如春礁击,著一層夾襖步出監(jiān)牢的瞬間逗载,已是汗流浹背更耻。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評論 1 269
  • 我被黑心中介騙來泰國打工食侮, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留锯七,地道東北人域蜗。 一個月前我還...
    沈念sama閱讀 47,776評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像丝蹭,于是被迫代替她去往敵國和親坪蚁。 傳聞我的和親對象是個殘疾皇子贱田,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,652評論 2 354

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