react hook 函數(shù) 10分鐘搞懂

主要介紹 useState useEffect useReducer useContext 用法

你還在為該使用無狀態(tài)組件(Function)還是有狀態(tài)組件(Class)而煩惱嗎蠢终?——擁有了hooks,你再也不需要寫Class了辆琅,你的所有組件都將是Function。

你還在為搞不清使用哪個生命周期鉤子函數(shù)而日夜難眠嗎?——擁有了Hooks,生命周期鉤子函數(shù)可以先丟一邊了婿牍。

你在還在為組件中的this指向而暈頭轉(zhuǎn)向嗎?——既然Class都丟掉了惩歉,哪里還有this等脂?你的人生第一次不再需要面對this俏蛮。

一個最簡單的Hooks

首先讓我們看一下一個簡單的有狀態(tài)組件:


image

我們再來看一下使用hooks后的版本:

b4f68ab8f0584ebcb87ab0b1f27f7e08.png

是不是簡單多了!可以看到上遥, Example變成了一個函數(shù)搏屑,但這個函數(shù)卻有自己的狀態(tài)(count),同時它還可以更新自己的狀態(tài)(setCount)粉楚。這個函數(shù)之所以這么了不得辣恋,就是因為它注入了一個hook-- useState,就是這個hook讓我們的函數(shù)變成了一個有狀態(tài)的函數(shù)模软。

除了 useState這個hook外伟骨,還有很多別的hook,比如 useEffect提供了類似于 componentDidMount等生命周期鉤子的功能燃异, useContext提供了上下文(context)的功能等等携狭。

Hooks本質(zhì)上就是一類特殊的函數(shù),它們可以為你的函數(shù)型組件(function component)注入一些特殊的功能回俐。咦逛腿?這聽起來有點像被詬病的Mixins啊仅颇?難道是Mixins要在react中死灰復(fù)燃了嗎单默?當(dāng)然不會了,等會我們再來談兩者的區(qū)別忘瓦〉癜迹總而言之,這些hooks的目標(biāo)就是讓你不再寫class政冻,讓function一統(tǒng)江湖枚抵。

React為什么要搞一個Hooks?

想要復(fù)用一個有狀態(tài)的組件太麻煩了明场!

我們都知道react都核心思想就是汽摹,將一個頁面拆成一堆獨立的,可復(fù)用的組件苦锨,并且用自上而下的單向數(shù)據(jù)流的形式將這些組件串聯(lián)起來逼泣。但假如你在大型的工作項目中用react,你會發(fā)現(xiàn)你的項目中實際上很多react組件冗長且難以復(fù)用舟舒。尤其是那些寫成class的組件拉庶,它們本身包含了狀態(tài)(state),所以復(fù)用這類組件就變得很麻煩秃励。

那之前氏仗,官方推薦怎么解決這個問題呢?答案是:渲染屬性(Render Props)和高階組件(Higher-Order Components)夺鲜。我們可以稍微跑下題簡單看一下這兩種模式皆尔。

渲染屬性指的是使用一個值為函數(shù)的prop來傳遞需要動態(tài)渲染的nodes或組件呐舔。如下面的代碼可以看到我們的 DataProvider組件包含了所有跟狀態(tài)相關(guān)的代碼,而 Cat組件則可以是一個單純的展示型組件慷蠕,這樣一來 DataProvider就可以單獨復(fù)用了珊拼。

1c193f54aaf048b2970ca07704943a3e.png

雖然這個模式叫Render Props,但不是說非用一個叫render的props不可流炕,習(xí)慣上大家更常寫成下面這種:

d85dc3063f6a4de2b352738b44777147.png

高階組件這個概念就更好理解了澎现,說白了就是一個函數(shù)接受一個組件作為參數(shù),經(jīng)過一系列加工后每辟,最后返回一個新的組件剑辫。看下面的代碼示例影兽, withUser函數(shù)就是一個高階組件揭斧,它返回了一個新的組件莱革,這個組件具有了它提供的獲取用戶信息的功能峻堰。

df2c6592b22e454a9bc9cfc49efe0117.png

生命周期鉤子函數(shù)里的邏輯太亂了吧!

我們通常希望一個函數(shù)只做一件事情盅视,但我們的生命周期鉤子函數(shù)里通常同時做了很多事情捐名。比如我們需要在 componentDidMount中發(fā)起ajax請求獲取數(shù)據(jù),綁定一些事件監(jiān)聽等等闹击。同時镶蹋,有時候我們還需要在 componentDidUpdate做一遍同樣的事情。當(dāng)項目變復(fù)雜后赏半,這一塊的代碼也變得不那么直觀贺归。

classes真的太讓人困惑了!

我們用class來創(chuàng)建react組件時断箫,還有一件很麻煩的事情拂酣,就是this的指向問題。為了保證this的指向正確仲义,我們要經(jīng)常寫這樣的代碼: this.handleClick=this.handleClick.bind(this)婶熬,或者是這樣的代碼: <buttononClick={()=>this.handleClick(e)}>。一旦我們不小心忘了綁定this埃撵,各種bug就隨之而來赵颅,很麻煩。

還有一件讓我很苦惱的事情暂刘。我在之前的react系列文章當(dāng)中曾經(jīng)說過饺谬,盡可能把你的組件寫成無狀態(tài)組件的形式,因為它們更方便復(fù)用谣拣,可獨立測試商蕴。然而很多時候叠萍,我們用function寫了一個簡潔完美的無狀態(tài)組件,后來因為需求變動這個組件必須得有自己的state绪商,我們又得很麻煩的把function改成class苛谷。

在這樣的背景下,Hooks便橫空出世了格郁!

什么是State Hooks腹殿?

回到一開始我們用的例子,我們分解來看到底state hooks做了什么:

c8472d53562340348b2be7463665fb68.png

聲明一個狀態(tài)變量

6dbfc72c1004433c80beeae68b2ea856.png

useState是react自帶的一個hook函數(shù)例书,它的作用就是用來聲明狀態(tài)變量锣尉。 useState這個函數(shù)接收的參數(shù)是我們的狀態(tài)初始值(initial state),它返回了一個數(shù)組决采,這個數(shù)組的第 [0]項是當(dāng)前當(dāng)前的狀態(tài)值自沧,第 [1]項是可以改變狀態(tài)值的方法函數(shù)。

所以我們做的事情其實就是树瞭,聲明了一個狀態(tài)變量count拇厢,把它的初始值設(shè)為0,同時提供了一個可以更改count的函數(shù)setCount晒喷。

上面這種表達形式孝偎,是借用了es6的數(shù)組解構(gòu)(array destructuring),它可以讓我們的代碼看起來更簡潔凉敲。不清楚這種用法的可以先去看下我的這篇文章:30分鐘掌握ES6/ES2015核心內(nèi)容(上)衣盾。

如果不用數(shù)組解構(gòu)的話,可以寫成下面這樣爷抓。實際上數(shù)組解構(gòu)是一件開銷很大的事情势决,用下面這種寫法,或者改用對象解構(gòu)蓝撇,性能會有很大的提升果复。具體可以去這篇文章的分析:Array destructuring for multi-value returns (in light of React hooks),這里不詳細(xì)展開唉地,我們就按照官方推薦使用數(shù)組解構(gòu)就好据悔。

126a65e3966b416b893eb97abed431b7.png

讀取狀態(tài)值

f3c972c4723a45349d47d0e087dcdaf0.png

是不是超簡單?因為我們的狀態(tài)count就是一個單純的變量而已耘沼,我們再也不需要寫成 {this.state.count}這樣了极颓。

更新狀態(tài)

277e7afc1d404e3aa7754794b434922d.png

當(dāng)用戶點擊按鈕時,我們調(diào)用setCount函數(shù)群嗤,這個函數(shù)接收的參數(shù)是修改過的新狀態(tài)值菠隆。接下來的事情就交給react了,react將會重新渲染我們的Example組件,并且使用的是更新后的新的狀態(tài)骇径,即count=1躯肌。這里我們要停下來思考一下,Example本質(zhì)上也是一個普通的函數(shù)破衔,為什么它可以記住之前的狀態(tài)清女?

為什么hook記住狀態(tài),而不是每次初始化晰筛?

這里我們就發(fā)現(xiàn)了問題嫡丙,通常來說我們在一個函數(shù)中聲明的變量,當(dāng)函數(shù)運行完成后读第,這個變量也就銷毀了(這里我們先不考慮閉包等情況)曙博,比如考慮下面的例子:

81217645678645e69bcc7f74f22ec4e8.png

不管我們反復(fù)調(diào)用add函數(shù)多少次,結(jié)果都是1怜瞒。因為每一次我們調(diào)用add時父泳,result變量都是從初始值0開始的。那為什么上面的Example函數(shù)每次執(zhí)行的時候吴汪,都是拿的上一次執(zhí)行完的狀態(tài)值作為初始值惠窄?答案是:是react幫我們記住的。至于react是用什么機制記住的浇坐,留個懸念睬捶。

假如一個組件有多個狀態(tài)值怎么辦黔宛?

首先近刘,useState是可以多次調(diào)用的,所以我們完全可以這樣寫:

e075c454f5754f0a9655c07256c4b7b4.png

其次臀晃,useState接收的初始值沒有規(guī)定一定要是string/number/boolean這種簡單數(shù)據(jù)類型觉渴,它完全可以接收對象或者數(shù)組作為參數(shù)。唯一需要注意的點是徽惋,之前我們的 this.setState做的是合并狀態(tài)后返回一個新狀態(tài)案淋,而 useState是直接替換老狀態(tài)后返回新狀態(tài)。最后险绘,react也給我們提供了一個useReducer的hook踢京,如果你更喜歡redux式的狀態(tài)管理方案的話。

從ExampleWithManyStates函數(shù)我們可以看到宦棺,useState無論調(diào)用多少次瓣距,相互之間是獨立的。這一點至關(guān)重要代咸。為什么這么說呢蹈丸?

其實我們看hook的“形態(tài)”,有點類似之前被官方否定掉的Mixins這種方案,都是提供一種“插拔式的功能注入”的能力逻杖。而mixins之所以被否定奋岁,是因為Mixins機制是讓多個Mixins共享一個對象的數(shù)據(jù)空間,這樣就很難確保不同Mixins依賴的狀態(tài)不發(fā)生沖突荸百。

而現(xiàn)在我們的hook闻伶,一方面它是直接用在function當(dāng)中,而不是class够话;另一方面每一個hook都是相互獨立的虾攻,不同組件調(diào)用同一個hook也能保證各自狀態(tài)的獨立性。這就是兩者的本質(zhì)區(qū)別了更鲁。

react是怎么保證多個useState的相互獨立的霎箍?

還是看上面給出的ExampleWithManyStates例子,我們調(diào)用了三次useState澡为,每次我們傳的參數(shù)只是一個值(如42漂坏,‘banana’),我們根本沒有告訴react這些值對應(yīng)的key是哪個媒至,那react是怎么保證這三個useState找到它對應(yīng)的state呢顶别?

答案是,react是根據(jù)useState出現(xiàn)的順序來定的拒啰。我們具體來看一下:

5ffadde7918b422a9f8fa340171a2a3f.png

假如我們改一下代碼:

e47ea3ebbf4a42e1ac3247dad62a376a.png

這樣一來驯绎,

503fe0248f4e4a9786eb52b07ee11dc5.png

鑒于此,react規(guī)定我們必須把hooks寫在函數(shù)的最外層谋旦,不能寫在ifelse等條件語句當(dāng)中剩失,來確保hooks的執(zhí)行順序一致

什么是Effect Hooks?

我們在上一節(jié)的例子中增加一個新功能:

973780d510c143f8b8533006784955c0.png

我們對比著看一下册着,如果沒有hooks拴孤,我們會怎么寫?

0fe2d7928ab641d197824eabe6eb0712.png

我們寫的有狀態(tài)組件甲捏,通常會產(chǎn)生很多的副作用(side effect)演熟,比如發(fā)起ajax請求獲取數(shù)據(jù),添加一些監(jiān)聽的注冊和取消注冊司顿,手動修改dom等等芒粹。我們之前都把這些副作用的函數(shù)寫在生命周期函數(shù)鉤子里,比如componentDidMount大溜,componentDidUpdate和componentWillUnmount化漆。而現(xiàn)在的useEffect就相當(dāng)與這些聲明周期函數(shù)鉤子的集合體。它以一抵三猎提。

同時获三,由于前文所說hooks可以反復(fù)多次使用旁蔼,相互獨立。所以我們合理的做法是疙教,給每一個副作用一個單獨的useEffect鉤子棺聊。這樣一來,這些副作用不再一股腦堆在生命周期鉤子里贞谓,代碼變得更加清晰限佩。

useEffect做了什么?

我們再梳理一遍下面代碼的邏輯:

71a2b81ea3f04c7cb1717b71d07be8d7.png

首先裸弦,我們聲明了一個狀態(tài)變量 count祟同,將它的初始值設(shè)為0。然后我們告訴react理疙,我們的這個組件有一個副作用晕城。我們給 useEffecthook傳了一個匿名函數(shù),這個匿名函數(shù)就是我們的副作用窖贤。在這個例子里砖顷,我們的副作用是調(diào)用browser API來修改文檔標(biāo)題。當(dāng)react要渲染我們的組件時赃梧,它會先記住我們用到的副作用滤蝠。等react更新了DOM之后,它再依次執(zhí)行我們定義的副作用函數(shù)授嘀。

這里要注意幾點:

第一物咳,react首次渲染和之后的每次渲染都會調(diào)用一遍傳給useEffect的函數(shù)。而之前我們要用兩個聲明周期函數(shù)來分別表示首次渲染(componentDidMount)蹄皱,和之后的更新導(dǎo)致的重新渲染(componentDidUpdate)览闰。

第二,useEffect中定義的副作用函數(shù)的執(zhí)行不會阻礙瀏覽器更新視圖夯接,也就是說這些函數(shù)是異步執(zhí)行的焕济,而之前的componentDidMount或componentDidUpdate中的代碼則是同步執(zhí)行的纷妆。這種安排對大多數(shù)副作用說都是合理的盔几,但有的情況除外,比如我們有時候需要先根據(jù)DOM計算出某個元素的尺寸再重新渲染掩幢,這時候我們希望這次重新渲染是同步發(fā)生的逊拍,也就是說它會在瀏覽器真的去繪制這個頁面前發(fā)生。

useEffect怎么解綁一些副作用

這種場景很常見际邻,當(dāng)我們在componentDidMount里添加了一個注冊芯丧,我們得馬上在componentWillUnmount中,也就是組件被注銷之前清除掉我們添加的注冊世曾,否則內(nèi)存泄漏的問題就出現(xiàn)了缨恒。

怎么清除呢?讓我們傳給useEffect的副作用函數(shù)返回一個新的函數(shù)即可。這個新的函數(shù)將會在組件下一次重新渲染之后執(zhí)行骗露。這種模式在一些pubsub模式的實現(xiàn)中很常見岭佳。看下面的例子:

815762066faa4b1abadc040b4ea02c11.png

這里有一個點需要重視萧锉!這種解綁的模式跟componentWillUnmount不一樣珊随。componentWillUnmount只會在組件被銷毀前執(zhí)行一次而已,而useEffect里的函數(shù)柿隙,每次組件渲染后都會執(zhí)行一遍叶洞,包括副作用函數(shù)返回的這個清理函數(shù)也會重新執(zhí)行一遍。所以我們一起來看一下下面這個問題禀崖。

為什么要讓副作用函數(shù)每次組件更新都執(zhí)行一遍衩辟?

我們先看以前的模式:

b8ea99ea94de44f689272d3968574bda.png

很清除,我們在componentDidMount注冊波附,再在componentWillUnmount清除注冊惭婿。但假如這時候 props.friend.id變了怎么辦?我們不得不再添加一個componentDidUpdate來處理這種情況:

4a33e00c2e0947fd885f1a63d8e91d12.png

看到了嗎叶雹?很繁瑣财饥,而我們但useEffect則沒這個問題,因為它在每次組件更新后都會重新執(zhí)行一遍折晦。所以代碼的執(zhí)行順序是這樣的:

  • 頁面首次渲染

  • 替friend.id=1的朋友注冊

  • 突然friend.id變成了2

  • 頁面重新渲染

  • 清除friend.id=1的綁定

  • 替friend.id=2的朋友注冊

  • ...

怎么跳過一些不必要的副作用函數(shù)

按照上一節(jié)的思路钥星,每次重新渲染都要執(zhí)行一遍這些副作用函數(shù),顯然是不經(jīng)濟的满着。怎么跳過一些不必要的計算呢谦炒?我們只需要給useEffect傳第二個參數(shù)即可屁柏。用第二個參數(shù)來告訴react只有當(dāng)這個參數(shù)的值發(fā)生改變時卢未,才執(zhí)行我們傳的副作用函數(shù)(第一個參數(shù))督怜。

d9185fb8903e4f419377448ec9ca4a94.png

當(dāng)我們第二個參數(shù)傳一個空數(shù)組[]時熏纯,其實就相當(dāng)于只在首次渲染的時候執(zhí)行肌稻。也就是componentDidMount加componentWillUnmount的模式隅熙。不過這種用法可能帶來bug遍愿,少用奔滑。

還有哪些自帶的Effect Hooks?

useReducer

useReducer 則是 hooks 提供的一個類似于 redux 的 api耙考,讓我們可以通過 action 的方式來管理 context谜喊,或者 state

//reducer.js
const initialState = {count: 0};

function reducer(state, action) {
    switch (action.type) {
        case 'reset':
            return initialState;
        case 'increment':
            return {count: state.count + 1};
        case 'decrement':
            return {count: state.count - 1};
    }
}

export  default    function Counter({initialCount}) {
    const [state, dispatch] = useReducer( //  const [state, dispatch] = useReducer(reducer, initialState);
        reducer, initialState,
        {type: 'reset', payload: initialCount},  //,則在初始渲染期間應(yīng)用初始操作
    );
    return (
        <>
            Count: {state.count}
            <button onClick={() => dispatch({type: 'reset'})}>
                Reset
            </button>
            <button onClick={() => dispatch({type: 'increment'})}>+</button>
            <button onClick={() => dispatch({type: 'decrement'})}>-</button>
        </>
    );
}

useContext

const context = useContext(Context);
接受一個 context(上下文)對象(從React.createContext返回的值)并返回當(dāng)前 context 值倦始,由最近 context 提供程序給 context 斗遏。當(dāng)提供程序更新時,此 Hook 將使用最新的 context 值觸發(fā)重新渲染鞋邑。

//reducer.js
import React, { useReducer } from "react";

const initialState = 0;
const myContext = React.createContext();

function reducer(state, action) {
  switch (action.type) {
    case "reset":
      return initialState;
    case "increment":
      return { count: state.count + 1 };
    case "decrement":
      return { count: state.count - 1 };
    default:
      return state;
  }
}

const ContextProvider = props => {
  const [state, dispatch] = useReducer(reducer, { count: 0 });
  return (
    <myContext.Provider value={{ state, dispatch }}>
      {props.children}
    </myContext.Provider>
  );
};

export { reducer, myContext, ContextProvider };
//Counter.js
import React, { useContext } from "react";
import { myContext } from "./reducer";

function Counter() {
  const { state, dispatch } = useContext(myContext);
  return (
    <div>
      Counter Count: {state.count}
      <button onClick={() => dispatch({ type: "reset" })}>Reset</button>
      <button onClick={() => dispatch({ type: "increment" })}>+</button>
      <button onClick={() => dispatch({ type: "decrement" })}>-</button>
    </div>
  );
}

export default Counter;
//CounterTest.js
import React, { useContext } from "react";
import { myContext } from "./reducer";

function CounterTest() {
  const { state, dispatch } = useContext(myContext);
  return (
    <div>
      CounterTest Count: {state.count}
      <button onClick={() => dispatch({ type: "reset" })}>Reset</button>
      <button onClick={() => dispatch({ type: "increment" })}>+</button>
      <button onClick={() => dispatch({ type: "decrement" })}>-</button>
    </div>
  );
}

export default CounterTest;
//index.js
import React from "react";
import { ContextProvider } from "./reducer";
import Counter from "./Counter";
import CounterTest from "./CounterTest";

const App = () => {
  return (
    <div className="App">
      <ContextProvider>
        <Counter />
        <CounterTest />
      </ContextProvider>
    </div>
  );
};

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

除了上文重點介紹的useState和useEffect诵次,useContext,useReducer,react還給我們提供來很多有用的hooks:

  • useCallback

  • useMemo

  • useRef

  • useImperativeMethods

  • useMutationEffect

  • useLayoutEffect

我不再一一介紹账蓉,大家自行去查閱官方文檔。

怎么寫自定義的Effect Hooks?

為什么要自己去寫一個Effect Hooks? 這樣我們才能把可以復(fù)用的邏輯抽離出來逾一,變成一個個可以隨意插拔的“插銷”剔猿,哪個組件要用來,我就插進哪個組件里嬉荆,so easy归敬!看一個完整的例子,你就明白了鄙早。

比如我們可以把上面寫的FriendStatus組件中判斷朋友是否在線的功能抽出來汪茧,新建一個useFriendStatus的hook專門用來判斷某個id是否在線。

6b769400d32b4a9eb1cc782d97a24de7.png

這時候FriendStatus組件就可以簡寫為:

11ee813c5b254738bb6ca67774843ecf.png

假如這個時候我們又有一個朋友列表也需要顯示是否在線的信息:

27348fa2c0914e41aec9ce1f9642896b.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末限番,一起剝皮案震驚了整個濱河市舱污,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌弥虐,老刑警劉巖扩灯,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異霜瘪,居然都是意外死亡珠插,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門颖对,熙熙樓的掌柜王于貴愁眉苦臉地迎上來捻撑,“玉大人,你說我怎么就攤上這事缤底」嘶迹” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵个唧,是天一觀的道長江解。 經(jīng)常有香客問我,道長徙歼,這世上最難降的妖魔是什么犁河? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮鲁沥,結(jié)果婚禮上呼股,老公的妹妹穿的比我還像新娘。我一直安慰自己画恰,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布吸奴。 她就那樣靜靜地躺著允扇,像睡著了一般缠局。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上考润,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天狭园,我揣著相機與錄音,去河邊找鬼糊治。 笑死唱矛,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的井辜。 我是一名探鬼主播绎谦,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼粥脚!你這毒婦竟也來了窃肠?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤刷允,失蹤者是張志新(化名)和其女友劉穎冤留,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體树灶,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡纤怒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了天通。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片肪跋。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖土砂,靈堂內(nèi)的尸體忽然破棺而出州既,到底是詐尸還是另有隱情,我是刑警寧澤萝映,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布吴叶,位于F島的核電站,受9級特大地震影響序臂,放射性物質(zhì)發(fā)生泄漏蚌卤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一奥秆、第九天 我趴在偏房一處隱蔽的房頂上張望逊彭。 院中可真熱鬧,春花似錦构订、人聲如沸侮叮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽囊榜。三九已至审胸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間卸勺,已是汗流浹背砂沛。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留曙求,地道東北人碍庵。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像悟狱,于是被迫代替她去往敵國和親静浴。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,901評論 2 345