React進階(1)-理解Redux

前言

image

在React中,數(shù)據(jù)流是單向的,并且是不可逆的,這其實,也很好理解,之所以這么設(shè)計,是因為組件復(fù)用的特點

父(外部)組件向子(內(nèi)部)組件傳遞數(shù)據(jù)是通過自定義屬性props值的方式進行實現(xiàn)的,并且在子組件內(nèi)部通過this.props進行獲取,它并不能直接被修改,如果想要修改,那么得通過React內(nèi)置的一個setState的方法進行觸發(fā)

而子組件想要傳遞數(shù)據(jù)給父組件,是通過調(diào)用父組件的方法進行通信

一個組件可能存在著很多狀態(tài),組件之間有時需要進行通信,對于多個組件狀態(tài)維護,如果依舊用原來的方式,那么就比較復(fù)雜了的

那么Redux正好解決了這一問題.個人覺得,Redux學(xué)起來很抽象,的確是塊硬骨頭,但是高山始終是要越過的

下面就一起來學(xué)習(xí)下Redux的

您將在本文中學(xué)習(xí)到

  • Redux是什么

  • Redux的使用場景以及與不使用Redux的靈魂對比

  • Redux的工作流程

  • Redux的設(shè)計基本原則

本篇雖不涉及代碼層面上的,但是對后續(xù)編碼Redux非常重要,磨刀不誤砍柴工

如果想閱讀體驗更好,可戳鏈接,React進階(1)-理解Redux

Redux是什么?

官方解釋:JavaScript應(yīng)用程序的可預(yù)測的狀態(tài)容器(一個管理應(yīng)用程序狀態(tài)的框架)

通俗一點:管理組件公共數(shù)據(jù)狀態(tài)的容器(倉庫/區(qū)域)

解決的問題: 當(dāng)應(yīng)用組件擁有多個狀態(tài),并且組件之間需要共享數(shù)據(jù)狀態(tài)時,從原始的組件傳遞數(shù)據(jù)的方式中解脫出來,集中管理組件的狀態(tài)

你可以把Redux理解為一個倉庫,房產(chǎn)中介.擁有很多共享的房源的一個管理者,后面會有具體的例子

Redux的使用場景

從上面提到的Redux解決問題可以看出,Redux只是用來管理和維護組件的狀態(tài)的

React開發(fā)的模式就是組件化開發(fā),將一個大的應(yīng)用拆分成若干個小的應(yīng)用,然后拼接成一個大的應(yīng)用,而編寫一個大小應(yīng)用就是在編寫各個大小組件

而組件的顯示形態(tài)又取決于它的狀態(tài),這不區(qū)分于無論是外部的props還是內(nèi)部的state,而組件之間有時需要共享傳遞數(shù)據(jù),Redux僅僅就是用來管理這些組件的狀態(tài)的

在一些開發(fā)者眼里,項目里要是沒有用到Redux,就覺得很low,要么把Redux捧得高高在上,要么說都已經(jīng)快0202年了,都用React hook了,鄙視得不行,個人覺得完全沒有必要.

React與Redux本身就是解決兩個不同方向的問題,某種程度上講,React可以視為MVC架構(gòu)中的視圖層V,而Redux則是model數(shù)據(jù)層M,而C層往往是連接視圖層和model的連接器,往往處理前端數(shù)據(jù)請求,路由跳轉(zhuǎn)等業(yè)務(wù)邏輯

即使不用Redux,照樣能做小應(yīng)用,只是略復(fù)雜繁瑣一些而已,下面會介紹他們之間的對比

那么對于技術(shù)選型,什么時候用Redux什么時候不用?

以下是選用Redux的場景:

  • 項目非常龐大,公共組件與業(yè)務(wù)組件非常多,用戶的使用方式比較復(fù)雜

  • 不同身份的用戶角色權(quán)限管理(例如很多后臺管理系統(tǒng),普通用戶,超級管理員,VIP用戶)讀,寫權(quán)限管理等

  • 多個用戶之間可以協(xié)作實時操作(很多那種在線敏捷協(xié)作辦公文檔工具,多個用戶可以實時編輯操作同一份文檔等的,例如石墨文檔,語雀,confluence.釘釘?shù)鹊?

  • 需要與服務(wù)器大量的交互,或者使用了webscoket的,聊天,直播等應(yīng)用的

  • 視圖層view需要從多個來源獲取數(shù)據(jù)

....只要你發(fā)現(xiàn)React解決不了的問題,遇到多交互,多數(shù)據(jù)源的,那么就可以考慮使用Redux的

反之,則以下則是沒有必要使用Redux

  • UI層非常簡單,只是用于渲染,無復(fù)雜的數(shù)據(jù)交互,依賴外部的props就可以渲染組件

  • 用戶的使用方式比較簡單,頁面之間比較獨立,沒有互相協(xié)作

  • 與服務(wù)器之間沒有大量交互

當(dāng)你發(fā)現(xiàn)使用React實在解決不了的問題,在各個組件之間傳遞數(shù)據(jù)非常復(fù)雜,很痛苦時,那么就可以考慮使用Redux了的,只要你hold住,沒有所謂的高大上技術(shù),只有適合自己業(yè)務(wù)的技術(shù)

盲目引入Redux只會增加項目的復(fù)雜度,引入新的技術(shù)應(yīng)該是循序漸進的

不使用Redux與使用Redux的靈魂對比

下面這張組件樹狀態(tài)圖的對比就很好的解釋了使用Redux與不使用Redux的區(qū)別

使用Redux與不使用Redux.png

一個React應(yīng)用(例如:pc網(wǎng)站,手機app應(yīng)用,后臺管理系統(tǒng)等用React技術(shù)棧構(gòu)建的應(yīng)用)其實就是一顆由組件構(gòu)成的樹,如上圖所示,在這顆樹的根結(jié)點,最頂層的組件就是該應(yīng)用的本身,由于組件都是以樹結(jié)構(gòu)組織起來的,當(dāng)每個組件被渲染時,它都會遞歸地渲染下級組件
React構(gòu)建的應(yīng)用.png

最頂層的應(yīng)用根節(jié)點.png

假設(shè)紅色圓圈代表的是一個應(yīng)用的子組件,如果想要把該紅色圓圈組件的狀態(tài)數(shù)據(jù)傳遞給父級或者非父級組件,它是通過調(diào)用父組件的方法來實現(xiàn),這樣一層一層往上傳,如果組件樹很龐大的話,那么就會變得非常繁瑣

在小型項目中,Redux并不是必需的,但是使用Redux卻是一勞永逸的,管理組件的狀態(tài)方便得多,對于大型應(yīng)用來說,單純使用原始的數(shù)據(jù)傳遞方式

那么組件之間的傳值會變得非常復(fù)雜,如果要做一個大型的應(yīng)用,那么就需要在React的基礎(chǔ)上配置一個數(shù)據(jù)層的框架進行結(jié)合的使用

如果改為右邊的Redux處理方式,將紅色圓圈組件的狀態(tài)數(shù)據(jù)放到一個Store倉庫當(dāng)中集中進行管理,哪個組件需要的話,直接派發(fā)給哪個組件就可以了的.

在Redux中,要求把組件的數(shù)據(jù)放到公共的存儲倉庫(區(qū)域)當(dāng)中,讓組件盡可能的減少狀態(tài)數(shù)據(jù)存儲,換而言之,所有組件自身內(nèi)部狀態(tài)數(shù)據(jù)都不放在state里面了,把它放到Store這樣的一個存儲倉庫當(dāng)中去

其實本質(zhì)上來說,是放到reducer里面去管理,Store從Reducer中拿到返回的數(shù)據(jù)state,最后供外部組件的取用

當(dāng)紅色圓圈組件想要改變數(shù)據(jù)傳遞給其他組件時,只需要去改變Store里面的存儲紅色圓圈組件的數(shù)據(jù)就可以了

一旦Store公共存儲的狀態(tài)數(shù)據(jù)發(fā)生改變了的,由于其他組件是公用Store的數(shù)據(jù),那么其他組件就會感知到Store的數(shù)據(jù)發(fā)生了改變,從而自身組件也會跟著改變

只要Store公共存儲區(qū)域的數(shù)據(jù)發(fā)生改變,凡是共用了Store里面的數(shù)據(jù)的組件都會重新的取數(shù)據(jù)

這樣一來,紅色圓圈組件的數(shù)據(jù)就非常容易的傳遞給其他組件了,無論是它的父級組件還是兄弟,非兄弟組件的

Redux就是把組件的數(shù)據(jù)放到一個公共的區(qū)域(倉庫)中進行存儲,當(dāng)改變Store存儲區(qū)域里面的數(shù)據(jù)時,其他組件如果用到了公共區(qū)域的數(shù)據(jù),那么就會感知到數(shù)據(jù)的變化,它會自動的更新取Store中最新的數(shù)據(jù)

這樣話,無論你的應(yīng)用組件嵌套得有多么復(fù)雜,多么深,走的流程都是一樣的,組件之間并不會干擾,低耦合的效果

當(dāng)組件一修改,把修改的數(shù)據(jù)放到Store當(dāng)中,而其他組件又從Store當(dāng)中再來取,這樣的話,組件與組件之間并不是直接進行通信的,是通過這么一個store中間角色來實現(xiàn)數(shù)據(jù)的傳遞共享的.

這樣的話,組件的數(shù)據(jù)傳遞就簡單多了的,也避免了組件與組件之間頻繁通信,容易產(chǎn)生混亂的問題

Redux其實是Flux數(shù)據(jù)框架的一個替代演進,同樣強調(diào)的是單向的數(shù)據(jù)源,保持狀態(tài)只具備讀的能力,而數(shù)據(jù)改變只能通過純函數(shù)完成基本,這和原先中React的UI=render(data)完全吻合.

React與Redux是兩個獨立的框架,前者是用于組件視圖層的渲染,而后者是管理組件的數(shù)據(jù)

Redux的工作流程

現(xiàn)在已經(jīng)知道了使用Redux與不使用Redux的區(qū)別,那么現(xiàn)在是時候來了解一下Redux的工作流程了,下面這個流程圖對于理解Redux很重要 先附上一張Redux工作流的流程圖:以后會在代碼中逐步的體現(xiàn)

Redux工作流.png

上面的Redux工作流圖中,以中間為準(zhǔn):包括了Store,ReactComponents,Actions Creators,以及Reducers

其中Store代表的就是負(fù)責(zé)組件存儲所有公共狀態(tài)的數(shù)據(jù),全局只有一個Store.(這里你可以把它理解為類似生活當(dāng)中中介公司管理房源的倉庫(數(shù)據(jù)庫)的區(qū)域經(jīng)理)

實質(zhì)上:store就是把Reducer關(guān)聯(lián)到一起的一個對象,它提供dispatch(action)方法更新state,以及getState方法獲取state

React Components:指的是頁面上的任意一個組件(你可以理解為小區(qū)公寓樓里的每個房間,而你就是住在里面的租房用戶)

Actions Creators:具體要干什么事情,觸發(fā)的動作,可以看做一個交互動作,改變應(yīng)用狀態(tài)或view的更新,都需要通過觸發(fā)action來實現(xiàn),Action的執(zhí)行結(jié)果就是調(diào)用Dispatch來處理相應(yīng)的事情,實現(xiàn)頁面視圖view的更新,唯一的辦法就是調(diào)用dispatch派發(fā)action

它是一個javascript對象,是用來描述事件的行為的,對象里記錄了相關(guān)的信息,例如:todolist的添加,刪除list的這個具體操作,就是一個action

(當(dāng)你想要提出換房的時候,跟中介公司管理房源的經(jīng)理說,你要換個帶有沙發(fā),電視,配備廚房的兩室一廳的房子,因為增加人口了,現(xiàn)有的房子住不下了的,你要做的什么事情,提出的條件信息就是數(shù)據(jù)),這個動作可以理解為actions creators

在你提出換房的時候,房產(chǎn)中介公司經(jīng)理雖然手握很多房源,但是他也沒有辦法記得所有的房子相關(guān)信息,它需要去數(shù)據(jù)庫(倉庫)里去查,你常澈雎澹看到中介小哥帶你看房的時候

手上拿一個單子,Excel表格跟你介紹房源的時候,你可以把這個單子,Excel表格理解為一個實時記錄本,只要有房子出租去了,這個表格就會實時更新(新舊信息的核實對比),返回一張新的房源信息表單給房產(chǎn)中介的經(jīng)理

Reducer:可以把上面的用于實時更新記錄房源信息的記錄本稱為Reducer,它只用作于根據(jù)舊的房源與提出新的需求(動作),總是會返回一張新的記錄本給房產(chǎn)中介經(jīng)理

實質(zhì)上:Reducer是根據(jù)action發(fā)出的type(動作類型)來做什么事(返回最新的state給store等邏輯操作)

現(xiàn)在歸納一下整個流程:

我(租客/組件React Component)想要換一個xxx信息的房子(Actions creators,具體要做的什么事情),房產(chǎn)中介經(jīng)理收到了請求,他得根據(jù)你提供的一些需求信息去找相應(yīng)的房源信息

但是房源太多,需要借助一個實時的記錄本去查看符合條件的房源信息,當(dāng)查到符合條件的信息后,這個記錄本(Reducer)把最新的信息會返回給房產(chǎn)經(jīng)理(Store),最終把信息返回給用戶React Components,實現(xiàn)房子替換的更新

雖然文字啰嗦了點:但是Redux就是這么一回事,我要換大房子,房產(chǎn)中介經(jīng)理聽到后,它去記錄本里面去查,查到之后,返回到房產(chǎn)中介經(jīng)理,然后最終在返回給我,實現(xiàn)房子的替換

那么轉(zhuǎn)換為代碼理解:

頁面上的一個組件,想要獲取更新Store中的數(shù)據(jù),跟Store說,我點擊這個按鈕,要更新這個組件的數(shù)據(jù),要干什么事情,做的這個具體動作就是Actions Creators,這時會派發(fā)(dispatch) 該動作(action)給Store,Store會去Reducer里面去查一下,Reducer會返回一個新的結(jié)果給Store,Store拿到最新的數(shù)據(jù)結(jié)果后,返回給頁面上的組件,實現(xiàn)頁面組件的更新

大家可以先仔細(xì)體會上面這段文字的含義,在后續(xù)的實例代碼中,在回過頭來對比著代碼與文字進行理解的,后續(xù)還會在拿出來的

Redux的設(shè)計基本原則

在Redux中有以下幾個設(shè)計基本原則

  • 單向數(shù)據(jù)流

  • 唯一數(shù)據(jù)源

  • 保持狀態(tài)只讀

  • 數(shù)據(jù)的改變只能通過純函數(shù)reducer來完成

單向數(shù)據(jù)流: 這個其實與props不能直接被修改一樣,在父組件向子組件傳遞數(shù)據(jù)時是通過屬性的方式進行傳遞的,而子組件內(nèi)部通過this.props進行接收,但是外部傳遞過來的props屬性不能直接被修改,若想要修改,需要借助React內(nèi)置的setState方法進行觸發(fā)

唯一數(shù)據(jù)源: 它指的是組件的應(yīng)用狀態(tài)數(shù)據(jù)應(yīng)該只存在唯一的Store上,這一點是不同于Flux的,在Flux中允許有多個store捞慌。而在Redux中整個組件的應(yīng)用只保持一個Store,所有組件的數(shù)據(jù)源就是這個Store上的狀態(tài),可以將它Store理解為一個全局的變量對象

保持狀態(tài)state可讀: 不能直接的去修改狀態(tài),要修改Store的狀態(tài),必須要通過派發(fā)(dispatch)一個action對象去完成

然后組件渲染的對應(yīng)的界面要更改的話,實際更改的就是組件的狀態(tài),如果狀態(tài)都是只能讀不能修改的話,那么界面就不會更新變化了

想要更改用戶界面的渲染,就要改變組件的應(yīng)用狀態(tài),但時改變組件狀態(tài)的方法不是直接去修改狀態(tài)上的值,而是創(chuàng)建一個新的狀態(tài)對象返回給Redux,由Redux完成新的狀態(tài)的組裝

組件數(shù)據(jù)的改變只能通過純函數(shù)完成

所謂的純函數(shù),就是指Reducer,而Redux某種程度上講,它是Reducer+Flux的組合,其中這Redux的Red代表就是Reducer,而ux就是Flux,但是又不同于Flux,它更像是Flux的一個實現(xiàn),演進被啼。它是為了描述Action如何改變組件的狀態(tài)的

這也是為什么Redux這個名稱比較抽象的原因,其中Reducer類似一個數(shù)組中的迭代器函數(shù)reduce

var arr = [1,2,3,4,5,6]
var sum = arr.reduce(function reducer(prevValue, currentValue,index,array){
    console.log(`上一次調(diào)用回調(diào)返回的值(或者是提供的初始值): ${prevValue},數(shù)組中當(dāng)前被處理的元素: ${currentValue}, 當(dāng)前元素在數(shù)組中的索引: ${index}, 調(diào)用的數(shù)組: ${array}`);
  return prevValue+currentValue;
},0)
console.log(sum); // 21

VM1742:3 上一次調(diào)用回調(diào)返回的值(或者是提供的初始值): 0,數(shù)組中當(dāng)前被處理的元素: 1, 當(dāng)前元素在數(shù)組中的索引: 0, 調(diào)用的數(shù)組: 1,2,3,4,5,6
VM1742:3 上一次調(diào)用回調(diào)返回的值(或者是提供的初始值): 1,數(shù)組中當(dāng)前被處理的元素: 2, 當(dāng)前元素在數(shù)組中的索引: 1, 調(diào)用的數(shù)組: 1,2,3,4,5,6
VM1742:3 上一次調(diào)用回調(diào)返回的值(或者是提供的初始值): 3,數(shù)組中當(dāng)前被處理的元素: 3, 當(dāng)前元素在數(shù)組中的索引: 2, 調(diào)用的數(shù)組: 1,2,3,4,5,6
VM1742:3 上一次調(diào)用回調(diào)返回的值(或者是提供的初始值): 6,數(shù)組中當(dāng)前被處理的元素: 4, 當(dāng)前元素在數(shù)組中的索引: 3, 調(diào)用的數(shù)組: 1,2,3,4,5,6
VM1742:3 上一次調(diào)用回調(diào)返回的值(或者是提供的初始值): 10,數(shù)組中當(dāng)前被處理的元素: 5, 當(dāng)前元素在數(shù)組中的索引: 4, 調(diào)用的數(shù)組: 1,2,3,4,5,6
VM1742:3 上一次調(diào)用回調(diào)返回的值(或者是提供的初始值): 15,數(shù)組中當(dāng)前被處理的元素: 6, 當(dāng)前元素在數(shù)組中的索引: 5, 調(diào)用的數(shù)組: 1,2,3,4,5,6
VM1742:6 21

上面的代碼中是做一個簡單的累加,reducer函數(shù)接收四個參數(shù),第一個參數(shù)是上一次調(diào)用返回的結(jié)果,第二個參數(shù)是當(dāng)前被處理的元素的值,第三個是當(dāng)前元素在數(shù)組中的索引,第四個是調(diào)用的原數(shù)組

這個reduce的方法接收一個函數(shù)作為累加器,reduce 為數(shù)組中的每一個元素依次執(zhí)行回調(diào)函數(shù)

而在Redux中,每個reducer純函數(shù)如下所示
其中reducer函數(shù)的第一個參數(shù)state是指當(dāng)前的狀態(tài)值,而第二個參數(shù)action是接收到的action對象

而reducer函數(shù)要做的事情就是根據(jù)state和action的值產(chǎn)生一個新的對象返回給Store,它是定義整個組件應(yīng)用狀態(tài)如何更改,根據(jù)Action動作行為去更新Store中的狀態(tài)

注意的是reducer必須是純函數(shù),換句話說,reducer函數(shù)的返回結(jié)果必須完全由參數(shù)state和action決定,而且不產(chǎn)生任何的副作用,也不能修改參數(shù)state和action對象

如下一個典型的reducer示例,reducer只是一個函數(shù)名稱,你是可以任意取的,如下一個計數(shù)的counter純函數(shù)

function counter(state = 0, action) {
  switch (action.type) {
  case 'INCREMENT':
    return state + 1;
  case 'DECREMENT':
    return state - 1;
  default:
    return state;
  }
}

從上面的例子看得出,reducer函數(shù)不光接受action為參數(shù),還接受state參數(shù),也就是說,Redux中的reduce函數(shù)只負(fù)責(zé)計算組件的狀態(tài),卻不負(fù)責(zé)存儲組件的狀態(tài)

在Reducer函數(shù)中往往包含action.type為判斷條件的if-else或者switch語句,根據(jù)action,總是返回一個新的狀態(tài),這個新的狀態(tài)的結(jié)果返回給store,store就會將原來上一次的state進行替換更新,最終達到改變state這么一個過程

結(jié)語

本節(jié)主要介紹了Redux,它與React是兩個獨立的產(chǎn)品,兩個框架做的事情的方向不一樣,React是用作于視圖層的渲染,也相當(dāng)于MVC中的V層,而Redux它是用于管理組件公共數(shù)據(jù)的Model層,更近一步講,它是Reducer與Flux的一種結(jié)合,改進.

對比了使用Redux與不使用Redux的區(qū)別,以及Redux的工作流,最后Redux的設(shè)計基本原則,其中前兩個,個人覺得對于理解Redux是非常重要的

當(dāng)然現(xiàn)在也可以使用高階組件,React hooks的寫法,可以不用Redux了的,也有類似于dva這樣的框架,基于Redux以及中間件(Redux-saga)的數(shù)據(jù)流方案

但是Redux依然是主流,只要你能夠應(yīng)付項目中開發(fā)需求,哪個用得爽就用哪個的,Redux雖然確實是繞了一些,有時候在各個文件之間進行來回切換,對于模塊化的拆分,如果不是很清楚Redux的使用流程,無論是后續(xù)維護還是迭代升級,都挺痛苦的

本篇并不是什么高大上的內(nèi)容,比較淺顯,概念性的文字比較多,后續(xù)會結(jié)合具體的代碼進一步理解Redux

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市锰什,隨后出現(xiàn)的幾起案子瓢省,更是在濱河造成了極大的恐慌,老刑警劉巖猬膨,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異圈浇,居然都是意外死亡寥掐,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門磷蜀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來召耘,“玉大人,你說我怎么就攤上這事褐隆∥鬯” “怎么了?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵庶弃,是天一觀的道長衫贬。 經(jīng)常有香客問我,道長歇攻,這世上最難降的妖魔是什么固惯? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮缴守,結(jié)果婚禮上葬毫,老公的妹妹穿的比我還像新娘。我一直安慰自己屡穗,他們只是感情好贴捡,可當(dāng)我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著村砂,像睡著了一般烂斋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天汛骂,我揣著相機與錄音罕模,去河邊找鬼。 笑死香缺,一個胖子當(dāng)著我的面吹牛手销,可吹牛的內(nèi)容都是我干的歇僧。 我是一名探鬼主播图张,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼诈悍!你這毒婦竟也來了祸轮?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤侥钳,失蹤者是張志新(化名)和其女友劉穎适袜,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體舷夺,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡苦酱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了给猾。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片疫萤。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖敢伸,靈堂內(nèi)的尸體忽然破棺而出扯饶,到底是詐尸還是另有隱情,我是刑警寧澤池颈,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布尾序,位于F島的核電站,受9級特大地震影響躯砰,放射性物質(zhì)發(fā)生泄漏每币。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一琢歇、第九天 我趴在偏房一處隱蔽的房頂上張望兰怠。 院中可真熱鬧,春花似錦矿微、人聲如沸痕慢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽掖举。三九已至,卻和暖如春娜庇,著一層夾襖步出監(jiān)牢的瞬間塔次,已是汗流浹背方篮。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留励负,地道東北人藕溅。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像继榆,于是被迫代替她去往敵國和親巾表。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,440評論 2 348

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