React Native - Redux 入門

React Redux API Overview

從上周開始一直在看 Redux 相關(guān)的文檔和資料姑子,一開始一連幾天都沒有進(jìn)展,只能一邊看文檔一邊默默 debug测僵,到今天總算稍微理解了一點(diǎn)兒街佑,于是趕緊開始寫這篇博客,目的是一點(diǎn)點(diǎn)記錄下自己入門 Redux 的過程以及作為一個(gè) React Native 菜鳥對(duì)使用 Redux 的心得體會(huì)捍靠。

(長文預(yù)警:本文最佳閱讀方式是先把 Redux 文檔 以及 React Redux API 文檔 在另一個(gè)瀏覽器中打開沐旨,隨時(shí)對(duì)比參考,然后把 Demo 項(xiàng)目打開榨婆,看到有疑惑的地方磁携,隨時(shí)停下來動(dòng)手寫一寫、改一改代碼良风,debug 下谊迄,然后再接著看)

00 What's Redux?

首先看下官方文檔的解釋『Redux is a predictable state container for JavaScript apps』,大致可以翻譯為 Redux 是一個(gè)專為 JavaScript 應(yīng)用設(shè)計(jì)的可預(yù)測的狀態(tài)容器烟央。

我的理解:如果把我們的 app 比做銷售柜臺(tái)的話统诺,Redux 其實(shí)就像一個(gè)自動(dòng)售貨機(jī),它可以幫助我們管理商品(組件)的各種狀態(tài)吊档。

我們知道在一個(gè) RN 項(xiàng)目中篙议,一般會(huì)定義許許多多的組件,每個(gè)組件都有自己的 State怠硼,通常情況下會(huì)通過 setState 去更改組件狀態(tài)或者響應(yīng)用戶的在 UI 上的輸入鬼贱,但是隨著一個(gè) App 的內(nèi)容的增加以及邏輯復(fù)雜度的上升,組件的的狀態(tài)會(huì)變得越來越臃腫香璃,繼而變得難以維護(hù)(維護(hù)困難也是 RN 最大的痛點(diǎn))这难。所以,這個(gè)時(shí)候就該 Redux 出場了葡秒,我們通過引入它來幫助我們管理組件的狀態(tài)姻乓。

簡單來說嵌溢,有了 Redux 之后,我們基本上就不需要自己去 setState 了蹋岩,因?yàn)閹缀跛械?State 的變化都可以交給 Redux 來管理赖草。

01 Core Concept

Redux 中有四個(gè)核心的概念是需要我們掌握的,分別是 Actions, Reducers, Store 以及 Data Flow(強(qiáng)烈推薦看一遍 Redux 文檔 里對(duì)這幾個(gè)概念的介紹)剪个。

看過文檔后差不多就可以知道秧骑,我們通過在需要改變 state 的地方發(fā)送(dispatch) action,然后在 reducer 中根據(jù) action 的 type 進(jìn)行處理(返回增刪改后的 state)扣囊,而 state 則是根據(jù) reducer 的組合結(jié)構(gòu)保存在 store 的 state 樹中的乎折。

文字太枯燥,來看下面這張圖輔助理解:

Redux Data Flow (simple)

我簡單分析下這張圖吧:

  1. 首先 React 組件綁定了 Redux 之后(主要借助 React-Redux侵歇,下面會(huì)說到)骂澄,就可以使用 store.dispatch() 去發(fā)送事件了,比如在按鈕的點(diǎn)擊事件中發(fā)送 action惕虑;
  2. store 接收到 action 之后坟冲,會(huì)把之前的 state 連同發(fā)送的 action 一起傳遞給 reducer,然后 reducer 會(huì)根據(jù)我們定義好的處理方式去處理 action (增刪改 state)枷遂,然后返回新的 state 讓 store 去更新全局 state 樹樱衷;
  3. 最終 store 會(huì)把新的 state 返回給發(fā)送 action 的地方好讓 React 組件更新 UI。

Q & A

這里再總結(jié)一些 Redux 新手會(huì)比較疑惑的點(diǎn):

問:什么是 Action Creator ?

答:顧名思義酒唉,Action Creator 就是生成 action 的函數(shù),我們知道 action 是一個(gè)對(duì)象沸移,其中攜帶了一些用于更新 state 的數(shù)據(jù)痪伦。想象一下,如果我們每次發(fā)送事件的時(shí)候都自己定義一個(gè) action 對(duì)象雹锣,那么無疑是非常容易出錯(cuò)的网沾。而使用 Action Creator 后,管理 action 就容易多了蕊爵,而且也不用擔(dān)心在 action 中用錯(cuò)屬性了辉哥,因?yàn)橹灰?Action Creator 中定義好參數(shù)后,我們就可以在發(fā)送該 action 的地方確定需要攜帶哪些數(shù)據(jù)了攒射。比如:

export function changeText(text, color) {
  return {
    type: CHANGE_TEXT,
    text,
    color,
  };
}

問:reducer 當(dāng)中是如何更改 state 的醋旦?可以在 reducer 中發(fā)請求嗎?

答:不可以会放!注意饲齐,reducer 只是通過接收 action 去處理 state 的變化,我們不可以在 reducer 中引入變化咧最。引用文檔上的話:

Remember that the reducer must be pure. Given the same arguments, it should calculate the next state and return it. No surprises. No side effects. No API calls. No mutations. Just a calculation.

也就是說 reducer 必須是純函數(shù)捂人,接收輸入御雕,返回輸出,只是純粹的計(jì)算滥搭。舉個(gè)例子:

function textReducer(state = {}, action) {
  let text = action.text;
  let color = action.color;
  // 判斷 action 類型
  switch (action.type) {
    case CHANGE_TEXT:
      // 返回新狀態(tài)
      return Object.assign({}, state, {
        text: '新文字:' + text,
        color: color
      });
    default:
      return state;
  }
}

需要注意的是酸纲,我們不可以改變原來的 state,也就是要保持 Object.assign() 中的第一個(gè)參數(shù)為空瑟匆,當(dāng)然也可以使用擴(kuò)展運(yùn)算符 {...state, {newState}} 來達(dá)到同樣的目的福青。

問:React 組件是如何更新的?

答:哈哈脓诡,這個(gè)其實(shí)就是真正體現(xiàn)出 Redux 優(yōu)勢的地方无午。之前說過有了 Redux 之后我們就不需要自己去管理 state,這是怎么做到的呢祝谚?其實(shí)當(dāng)我們把所有的 state 都交給 Redux 之后宪迟,Redux 在 store 中就保存了我們應(yīng)用所有的 state (state tree),這意味著我們可以在任意位置獲取到這些 state交惯。而在 RN 中次泽,我們通過 React-Redux 來連接 Redux 和 RN 組件,然后在組件中通過將 state 映射成 props 來使用席爽,而且我們還可以將 dispatch 也映射成 props 來使用意荤。也就是說,我們只需要使用 this.props.xxx 就可以完成數(shù)據(jù)的展示只锻、響應(yīng)用戶輸入以及 UI 變化了玖像,是不是非常神奇?后面 03 段會(huì)詳細(xì)說我們是怎么通過 React-Redux 來做到這一點(diǎn)的齐饮。

02 Basic Usage

了解了 Redux 基本概念之后就可以來學(xué)習(xí)一下如何使用了捐寥。這一節(jié)主要介紹 API 的使用。

Store

之前舉了個(gè) Action Creator 和 reducer 的例子祖驱,也知道了我們需要通過 store 來將這兩者綁定在一起握恳,但是 store 究竟還有哪些作用呢?store 主要有以下職責(zé):

可以看出 store 就像母體一樣捺僻,即保存了狀態(tài)又連接了 Action Creator 和 reducer乡洼。但是究竟是怎么連接的呢?

首先匕坯,之前說過我們的 reducer 可以定義 store 保存的 state 樹結(jié)構(gòu)束昵,為什么呢?因?yàn)?reducer 是可以層層組合的醒颖。通常一個(gè)組件會(huì)有很多層級(jí)以及類型(比如 UI 和數(shù)據(jù))的 state妻怎,我們不可能全都把他們定義在一個(gè) reducer 里,這樣代碼會(huì)變得又長又難以維護(hù)泞歉。正確的做法是我們應(yīng)該把一個(gè) reducer 拆分成多個(gè) reducer 后再通過某種方式將它們組合起來逼侦。

combineReducers(reducers)

最常見的就是使用 combineReducers() 方法來組合 reducer匿辩,它可以把多個(gè) reducer 合并成一個(gè) reducer 對(duì)象,而合并后的 reducer 的層級(jí)結(jié)構(gòu)就是我們訪問 state 時(shí)的層級(jí)結(jié)構(gòu)榛丢。接收的參數(shù)是一個(gè) reducer 對(duì)象铲球,我們可以自己指定 key,也可以直接組合晰赞,比如:

const allReducers = combineReducers({textReducer, imageReducer, videoRed: videoReducer});

createStore(reducer, [preloadedState], [enhancer])

當(dāng)把多個(gè) reducer 合并成一個(gè)之后稼病,我們就可以通過 createStore 來創(chuàng)建 store 了,它唯一必須的參數(shù)是 reducer掖鱼,也就是我們 combineReducer(reducers) 返回的 reducer然走。

第二個(gè)參數(shù)是可選的初始狀態(tài) preloadedState。我們可以從服務(wù)器讀取初始狀態(tài)戏挡,或者在 app 啟動(dòng)時(shí)從本地?cái)?shù)據(jù)讀取初始狀態(tài)芍瑞。如果使用了 combineReducer() 后的 reducer 作為第一個(gè)參數(shù),那么 preloadedState 就必須是結(jié)構(gòu)和 reducer 中的結(jié)構(gòu)保持一致褐墅。

第三個(gè)參數(shù)也是可選的 enhancer拆檬,接收的是一個(gè)函數(shù),可以是你想要提供的第三方的功能妥凳,比如 Redux 自帶的 applyMiddleware()竟贯,這個(gè)屬于高階的內(nèi)容,以后有時(shí)間會(huì)寫寫逝钥。舉個(gè)例子:

const allReducers = combineReducers({textReducer});

let store = createStore(allReducers, applyMiddleware(thunkMiddleware));

export default store;

createStore() 返回的 store 就是保存了應(yīng)用全局 state 的對(duì)象了屑那,這個(gè)時(shí)候我們就可以使用 getState() 并且根據(jù) reducer 的層級(jí)來訪問保存在其中的 state 了!

Others...

其實(shí)核心的 API 就是以上這些晌缘,但是下面這些也是比較常見的齐莲,這里貼個(gè)鏈接自己看吧(???)

03 Combine with React-Redux

理解了 Redux 的核心概念以及基本 API 之后,我們就可以開始嘗試學(xué)習(xí)如何在 RN 中使用 Redux 了磷箕。在 RN 中,我們一般會(huì)結(jié)合 React-Redux 來使用 Redux阵难,通過它我們可以很方便地把 Redux 和 RN 組件綁定在一起岳枷。React-Redux 也是 Redux 官方推薦的用來和 React 綁定 的框架,其實(shí)我也有點(diǎn)奇怪為什么不直接把 React-Redux 加入到 Redux 中去呜叫?(?_?ヾ

同樣的空繁,在介紹 React-Redux 具體用法之前,建議先把 API 文檔 打開放邊上供隨時(shí)參考朱庆。

<Provider>

從文檔上可以發(fā)現(xiàn)盛泡,React-Redux 的 API 分為兩部分,分別是 <Provider store> 以及connect() 方法娱颊。connect() 方法用于連接單個(gè)的 RN 組件和 Redux Store傲诵,而 Provider 則作為根布局用于包裝所有的 RN 組件凯砍,使得其中使用了 connect() 后的組件可以自由訪問 Redux Store

比如假設(shè)你的根部組件是 <Main/> (如果你使用 react-native-router-flux 作為 navigation 的話拴竹,那么根布局就是 <Router>)悟衩,用 <Provider> 包裝后就是這樣的:

<Provider store={store}>
    <Main />
</Provider>

而在你的容器(Container,下面會(huì)說到)中栓拜,需要使用 connect() 方法來連接 RN 組件和 store座泳,像這樣:

export default connect(mapStateToProps, {changeText, changeBack})(Main);

connect()

React-Redux 的核心就是 connect() 方法了,所以下面詳細(xì)介紹下 connect() 方法的各個(gè)參數(shù)幕与。

調(diào)用 connect() 方法不會(huì)修改組件挑势,但是會(huì)返回一個(gè)已經(jīng)和 store 建立連接后的新組件,它使用了裝飾器模式啦鸣,裝飾的是 connectAdcanced()潮饱,這個(gè)方法返回一個(gè)接收需要連接的組件的方法(比如上面的 Main)。

它的參數(shù)如下(建議參照文檔看赏陵,我的翻譯也許有誤):

mapStateToProps(state, [ownProps])

這是一個(gè) function 類型的參數(shù)饼齿。

如果指定了這個(gè)參數(shù),那么返回的新組件就會(huì)接收到 store 的更新蝙搔。也就是說每次 store 發(fā)生更新時(shí)這個(gè)方法都會(huì)被調(diào)用缕溉。使用方式如下:

參數(shù):
  • state: 即 state 發(fā)生更新后接收到的新 state
  • ownProps: 可選,新組件接收到的 props吃型,如果指定了該值证鸥,那么這個(gè)方法也會(huì)被調(diào)用
返回值:
  • 必須是對(duì)象 object,并且該對(duì)象會(huì)被合并到組件的 props 中去勤晚。我們一般將接收到的 state 里面關(guān)于該組件有用到的部分取出枉层,映射成對(duì)應(yīng)的 props 就可以了,其實(shí)這個(gè)方法就是一個(gè)選擇器(selector

Tips: 如果不想接收到 state 的更新赐写,可以傳 nullundifined

mapDispatchToProps(dispatch, [ownProps]) or Action Creators

這是一個(gè) functionobject 類型的參數(shù)鸟蜡。

如果指定的是 object,那么其中的每個(gè)屬性必須是都是 Action Creator挺邀,每個(gè) Action Creator 都會(huì)被包裝到 dispatch() 中揉忘,并且合并到組件的 props 中去。

如果指定的是 function端铛,使用如下:

參數(shù):
  • dispatch: store 的 dispatch() 方法泣矛,你可以自己決定如何使用 dispatch 去發(fā)送事件(當(dāng)然也是通過 Action Creator),比如使用 bindActionCreators()
  • ownProps: 可選禾蚕,和 mapStateToProps 一樣也是新組件接收到的 props
返回值:
  • 同樣是一個(gè)對(duì)象 object您朽,會(huì)被合并到 props 中作為發(fā)送事件的方法來使用

Tips: 如果不指定該參數(shù)(mapDispatchToProps or Action Creator)那么 React- Redux 默認(rèn)會(huì)把 dispatch 方法注入到組件中,方便你自己手動(dòng)去調(diào)用 Action Creator换淆。

mergeProps(stateProps, dispatchProps, ownProps)

這是一個(gè) function 類型的參數(shù)哗总。

該方法用于將前面兩個(gè)參數(shù)返回的對(duì)象以及組件自己的 props 進(jìn)行重新組合或者過濾几颜,一般如果 props 較多的話,我們可以指定這個(gè)方法來對(duì) props 進(jìn)行篩選魂奥,然后再合并到組件中菠剩。使用方法如下:

參數(shù):
  • stateProps: 表示 mapStateToProps() 返回的對(duì)象

  • dispatchProps: 表示 mapDispatchToProps() 返回的對(duì)象

  • ownProps: 組件自己的 props

返回值:
  • 篩選后的對(duì)象,將會(huì)被合并到組件的 props 中去

Tips: 如果不指定該方法耻煤,默認(rèn)將調(diào)用 Object.assign({}, ownProps, stateProps, dispatchProps) 來合并所有的 props具壮。

options

這是一個(gè) object 類型的參數(shù)。

該方法用于定制連接器的行為哈蝇,具體可使用的參數(shù)有:

  • [pure] (Boolean): 如果為 true 則當(dāng) state/props 值沒有發(fā)生變化的時(shí)候則不重新渲染(rerender)或者調(diào)用 mapStateToProps() or mapDispatchToProps() or ownProps棺妓,前提是組件必須是"純"的(PureComponent?)炮赦,不依賴組件內(nèi)部的 state 而只依賴 props 和 Redux store怜跑。

  • [areStatesEqual] (Function): 當(dāng)是組件時(shí),比較接收到的新 state 和之前的值吠勘,默認(rèn)值 strictEqual (===)

  • [areOwnPropsEqual] (Function): 當(dāng)是組件時(shí)性芬,比較接收到的新 props 和之前的值,默認(rèn)值 shallowEqual

  • [areStatePropsEqual] (Function): 當(dāng)是組件時(shí)剧防,比較 mapStateToProps() 接收到的新 state 和之前的值植锉,默認(rèn)值 shallowEqual

  • [areMergedPropsEqual] (Function): 當(dāng)是組件時(shí),比較 mergeProps() 接收到的新 props 和之前的值峭拘,默認(rèn)值 shallowEqual

  • [storeKey] (String): 從當(dāng)前上下文中讀取 store 的 key俊庇,當(dāng)你有多個(gè) store 的時(shí)候才會(huì)使用這個(gè)參數(shù),不推薦使用多個(gè) store鸡挠,默認(rèn)值 store

Others

當(dāng)然辉饱,以上是核心 API,下面兩個(gè)方法不是很常用拣展,所以不多介紹了彭沼,自己看去吧~′???`

04 Show Me The Code

能看到這里說明你真的很好學(xué)啊,既然這樣那就一起來擼一下代碼吧(??????)备埃。Demo 地址:aJIEw/Redux

首先說明下溜腐,以下的項(xiàng)目分包是推薦的做法,你不一定需要完全遵守:

  • components [folder]
  • containers [folder]
  • redux [folder]
    • actions [folder]
    • reducers [folder]
    • store.js [file]

Components & Containers

Components 和 Containers 下面放的是兩種不同的組件瓜喇。這里的 Component 和 React 中的 Component 是有區(qū)別的,專指那些只是用來展示數(shù)據(jù)的歉糜、無狀態(tài)組件乘寒。Components 的特點(diǎn)是:1)通過 props 來接收數(shù)據(jù);2)可在多處復(fù)用匪补。由于是單純用于展示的組件伞辛,我們一般不會(huì)在 Components 中發(fā)起網(wǎng)絡(luò)請求烂翰、進(jìn)行本地存儲(chǔ)等操作。

而 Containers 指的是一個(gè)小的模塊蚤氏,用來連接數(shù)據(jù)并且可以修改數(shù)據(jù)的組件甘耿。Containers 一般會(huì)通過組合 Components 來使用,我們會(huì)在其中處理用戶輸入竿滨、狀態(tài)變化佳恬,也可以發(fā)起網(wǎng)絡(luò)請求等操作。

Components 和 Containers 的最簡單的區(qū)分方法是:有沒有使用 React-Redux 的 connect() 連接組件于游。

而 redux 包下存放的當(dāng)然就是和 Redux 相關(guān)的內(nèi)容啦毁葱,actions 下存放 Action Creator,reducers 下存放 reducer贰剥,最外面的 store.js 則是創(chuàng)建 store 的地方了倾剿。

Demo

看代碼之前先看下我們的 demo 實(shí)現(xiàn)的效果吧:Change Text Demo

根據(jù)最近學(xué)到的 SSCCE 原則,我盡可能把這個(gè) demo 寫的足夠簡單蚌成,目的是幫助理解 React Redux 的使用前痘。

ChangeableText

這個(gè) Component 的作用很簡單——顯示文字,不過文字和顏色是可以改變的担忧。

export default class ChangeableText extends Component {
  render() {
    return (
      <Text style={{color: this.props.color, borderWidth: 2, padding: 8}}>{this.props.text}</Text>
    );
  }
}
Main

而作為 Container 的 Main 則組合了 ChangeableText 組件并且有兩個(gè)可點(diǎn)擊的按鈕用于改變文字芹缔。

class Main extends Component {
  render() {
    return (
      <View style={styles.container}>
        {/* 將從 state 映射而來的 props 傳入 Component 中,state 發(fā)生變化則 props 的值也會(huì)相應(yīng)地發(fā)生改變 */}
        <ChangeableText {...this.props}/>

        {/* 此時(shí)直接調(diào)用 props 上的 dispatcher */}
        <TouchableOpacity style={styles.changeText} onPress={() => this.props.actions.changeText('Hello', 'red')}>
          <Text>改變文字</Text>
        </TouchableOpacity>

        <TouchableOpacity onPress={() => this.props.actions.changeBack()}>
          <Text>恢復(fù)</Text>
        </TouchableOpacity>
      </View>
    );
  }
}

最重要的部分就是 connect() 方法啦涵妥,這里我使用了 bindActionCreators() 來創(chuàng)建 dispacher:

// 將 state 映射成 props乖菱,這里我們可以自由組合需要使用到的 state,只要是 store 樹中存在的 state 都可以直接拿來使用
function mapStateToProps(state) {
  return {
    text: state.textReducer.text,
    color: state.textReducer.color,
  }
}

function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators(TextChanger, dispatch)
  }
}

// 第二個(gè)參數(shù)如果是 Action Creator蓬网,則會(huì)被自動(dòng)映射成組件上的 props 作為 dispatcher 使用
export default connect(mapStateToProps, mapDispatchToProps)(Main);
Action Creators

沒啥好說的窒所,注意 type 是必須要有的。

export const CHANGE_TEXT = 'CHANGE_TEXT';
export const CHANGE_BACK = 'CHANGE_BACK';

export function changeText(text, color) {
  return {
    type: CHANGE_TEXT,
    text,
    color,
  };
}

export function changeBack() {
  return {
    type: CHANGE_BACK,
    text: 'Hi',
    color: 'black',
  }
}
reducers

如何組織 reducer 是門藝術(shù)帆锋,尤其是當(dāng) app 變得復(fù)雜之后吵取,不過我們現(xiàn)在不用考慮這個(gè)問題...

function textReducer(state = {text: 'Hi', color: 'black'}, action) {
  let text = action.text;
  let color = action.color;
  
  // 判斷 action 類型
  switch (action.type) {
    case CHANGE_TEXT:
      // 返回新狀態(tài)
      return Object.assign({}, state, {
        text: '新文字:' + text,
        color: color
      });
    case CHANGE_BACK:
      return {
        ...state,
        text,
        color
      };
    default:
      return state;
  }
}

export default textReducer;
store.js

最后就是創(chuàng)建 store 了:

const allReducers = combineReducers({textReducer});

let store = createStore(allReducers);

export default store;
Root

最最后,記得要把根組件用 <Provider> 包裝起來:

export default class Root extends Component {
  render() {
    return (
      // 連接組件和 store
      <Provider store={store}>
        <Main />
      </Provider>
    )
  }
}

OK锯厢,大致就這么簡單皮官,接下來就是運(yùn)行,debug实辑,看看 state 是怎么在組件中被傳遞的捺氢。

05 Sum Up

通過上面的介紹,配合官方文檔和 Demo剪撬,如果你有完整看完的話摄乒,相信對(duì)于如何使用 Redux 應(yīng)該基本沒問題了,所以這個(gè)時(shí)候就可以祭出這張圖了:

Redux Data Flow Full

這張圖可以說非常完美地展現(xiàn)了 Redux 的工作原理,值得細(xì)看馍佑。其中 middleware 屬于高級(jí)內(nèi)容沒有仔細(xì)講斋否,下次有時(shí)間的話會(huì)再續(xù)更。

Redux 可以說是管理 state 的神器拭荤,能把我們從混亂和無序中解救出來茵臭。希望這篇文章可以幫助想要學(xué)習(xí) Redux 的同學(xué)盡早入門~(?????)?~~

祝大家中秋快樂!


參考:

  1. React-Native 之 redux 與 react-redux
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末舅世,一起剝皮案震驚了整個(gè)濱河市旦委,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌歇终,老刑警劉巖社证,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異评凝,居然都是意外死亡追葡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門奕短,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宜肉,“玉大人,你說我怎么就攤上這事翎碑∶担” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵日杈,是天一觀的道長遣铝。 經(jīng)常有香客問我,道長莉擒,這世上最難降的妖魔是什么酿炸? 我笑而不...
    開封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮涨冀,結(jié)果婚禮上填硕,老公的妹妹穿的比我還像新娘。我一直安慰自己鹿鳖,他們只是感情好扁眯,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著翅帜,像睡著了一般姻檀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上涝滴,一...
    開封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天施敢,我揣著相機(jī)與錄音周荐,去河邊找鬼。 笑死僵娃,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的腋妙。 我是一名探鬼主播默怨,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼骤素!你這毒婦竟也來了匙睹?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤济竹,失蹤者是張志新(化名)和其女友劉穎痕檬,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體送浊,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡梦谜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了袭景。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片唁桩。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖耸棒,靈堂內(nèi)的尸體忽然破棺而出荒澡,到底是詐尸還是另有隱情,我是刑警寧澤与殃,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布单山,位于F島的核電站,受9級(jí)特大地震影響幅疼,放射性物質(zhì)發(fā)生泄漏米奸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一衣屏、第九天 我趴在偏房一處隱蔽的房頂上張望躏升。 院中可真熱鬧,春花似錦狼忱、人聲如沸膨疏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽佃却。三九已至,卻和暖如春窘俺,著一層夾襖步出監(jiān)牢的瞬間饲帅,已是汗流浹背复凳。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留灶泵,地道東北人育八。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像赦邻,于是被迫代替她去往敵國和親髓棋。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

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

  • 前言 本文 有配套視頻惶洲,可以酌情觀看按声。 文中內(nèi)容因各人理解不同,可能會(huì)有所偏差恬吕,歡迎朋友們聯(lián)系我討論签则。 文中所有內(nèi)...
    珍此良辰閱讀 11,898評(píng)論 23 111
  • 學(xué)習(xí)必備要點(diǎn): 首先弄明白,Redux在使用React開發(fā)應(yīng)用時(shí)铐料,起到什么作用——狀態(tài)集中管理 弄清楚Redux是...
    賀賀v5閱讀 8,880評(píng)論 10 58
  • 做React需要會(huì)什么余赢? react的功能其實(shí)很單一芯义,主要負(fù)責(zé)渲染的功能,現(xiàn)有的框架妻柒,比如angular是一個(gè)大而...
    蒼都閱讀 14,747評(píng)論 1 139
  • 技術(shù)棧: react + redux + webpack + react-router + ES6/7/8 + i...
    黃昏少年閱讀 3,075評(píng)論 0 19
  • (一) 我從一個(gè)遙邈的夢中醒來扛拨,記住了夢中一張似曾相識(shí)的臉。薩...
    丁滿1717閱讀 457評(píng)論 3 6