Redux 是 JavaScript 狀態(tài)容器,提供可預(yù)測(cè)化的狀態(tài)管理。 Redux 是在 Flux 的基礎(chǔ)上產(chǎn)生的,基本思想是保證數(shù)據(jù)的單向流動(dòng),同時(shí)便于控制、使用、測(cè)試。Redux 并不依賴于其它 JavaScript 庫(kù)。 Redux隨著 JavaScript 單頁(yè)應(yīng)用開(kāi)發(fā)日趨復(fù)雜,JavaScript 需要管理比任何時(shí)候都要多的 state (狀態(tài))。 這些 state 可能包括服務(wù)器響應(yīng)、緩存數(shù)據(jù)、本地生成尚未持久化到服務(wù)器的數(shù)據(jù),也包括 UI 狀態(tài),如激活的路由,被選中的標(biāo)簽,是否顯示加載動(dòng)效或者分頁(yè)器等等。 跟隨 Flux、CQRS 和 Event Sourcing 的腳步,通過(guò)限制更新發(fā)生的時(shí)間和方式,Redux 試圖讓 state 的變化變得可預(yù)測(cè)。這些限制條件反映在 Redux 的三大原則中:
Redux 主要分為三個(gè)部分 Action、Reducer、及 Store
嚴(yán)格的單向數(shù)據(jù)流是 Redux 架構(gòu)的設(shè)計(jì)核心。store.dispatch(action) -> reducer(state, action) -> store.getState() 構(gòu)成了一個(gè)“單向數(shù)據(jù)流”。 Redux 應(yīng)用中數(shù)據(jù)的生命周期遵循下面 4 個(gè)步驟:
Redux 與 FluxFlux 是一種應(yīng)用架構(gòu),或者說(shuō)是一種思想,它跟 React 本身沒(méi)什么關(guān)系,它可以用在 React 上,也可以用在別的框架上。
完整的 Flux 處理流程是這樣的:用戶通過(guò)與 view 交互或者外部產(chǎn)生一個(gè) Action,Dispatcher 接收到 Action 并執(zhí)行那些已經(jīng)注冊(cè)的回調(diào),向所有 Store 分發(fā) Action。通過(guò)注冊(cè)的回調(diào),Store 響應(yīng)那些與他們所保存的狀態(tài)有關(guān)的 Action。然后 Store 會(huì)觸發(fā)一個(gè) change 事件,來(lái)提醒 controller-views 數(shù)據(jù)已經(jīng)發(fā)生了改變。Controller-views 監(jiān)聽(tīng)這些事件并重新從 Store 中獲取數(shù)據(jù)。這些 controller-views 調(diào)用他們自己的 setState() 方法,重新渲染自身以及組件樹(shù)上的所有后代組件。 Redux 的靈感來(lái)源于 Flux 的幾個(gè)重要特性,它可以看作是 Flux 的一種實(shí)現(xiàn)。和 Flux 一樣,Redux 規(guī)定,將模型的更新邏輯全部集中于一個(gè)特定的層,都不允許程序直接修改數(shù)據(jù),而是用一個(gè)叫作 “action” 的普通對(duì)象來(lái)對(duì)更改進(jìn)行描述。不同的是:
Redux使用
應(yīng)用中所有的 state 都以一個(gè)對(duì)象樹(shù)的形式儲(chǔ)存在一個(gè)單一的 store 中。唯一改變 state 的辦法是觸發(fā) action,一個(gè)描述發(fā)生什么的對(duì)象。 // 這是一個(gè) reducer,形式為 (state, action) => state 的純函數(shù)。 function counter(state = 0, action) { switch (action.type) { case 'INCREMENT': return state + 1; case 'DECREMENT': return state - 1; default: return state; } } // 創(chuàng)建 Redux store 來(lái)存放應(yīng)用的狀態(tài) let store = createStore(counter); // 可以手動(dòng)訂閱更新,也可以事件綁定到視圖層。 store.subscribe(() => console.log(store.getState()) ); // 改變內(nèi)部 state 唯一方法是 dispatch 一個(gè) action。 store.dispatch({ type: 'INCREMENT' }); // 輸出:1 store.dispatch({ type: 'INCREMENT' }); // 輸出:2 store.dispatch({ type: 'DECREMENT' }); // 輸出:1 以上代碼,首先定義改變應(yīng)用狀態(tài)的對(duì)象,這個(gè)對(duì)象被叫做 action,而不是直接改變 state。然后編寫(xiě)專(zhuān)門(mén)的函數(shù)來(lái)決定每個(gè) action 如何改變應(yīng)用的 state,這個(gè)函數(shù)被叫做 reducer。 Redux只有一個(gè)單一的 store 和一個(gè)根級(jí)的 reduce 函數(shù)(reducer)。 隨著應(yīng)用越來(lái)越大,一方面,不能把所有的數(shù)據(jù)都放到一個(gè)reducer里面,另一方面,為每個(gè)reducer創(chuàng)建一個(gè)store,后續(xù)store的維護(hù)就顯得比較麻煩。combineReducers 輔助函數(shù)的作用是,把一個(gè)由多個(gè)不同 reducer 函數(shù)作為 value 的 object,合并成一個(gè)最終的 reducer 函數(shù),然后就可以對(duì)這個(gè) reducer 調(diào)用 createStore。合并后的 reducer 可以調(diào)用各個(gè)子 reducer,并把它們的結(jié)果合并成一個(gè) state 對(duì)象。state 對(duì)象的結(jié)構(gòu)由傳入的多個(gè) reducer 的 key 決定。 // 創(chuàng)建兩個(gè)reducer function todos(state = [], action) { switch (action.type) { case 'ADD_TODO': return state.concat([action.text]) default: return state } } function counter(state = 0, action) { switch (action.type) { case 'INCREMENT': return state + 1 case 'DECREMENT': return state - 1 default: return state } } // 將多個(gè)reducer合并成一個(gè) var combineReducers = require('../../lib/redux/redux').combineReducers; var rootReducer = combineReducers({ todos, counter }); var createStore = require('../../lib/redux/redux').createStore; var store = createStore(rootReducer); console.log(store.getState()) // { // counter: 0, // todos: [] // } store.dispatch({ type: 'ADD_TODO', text: 'Use Redux' }); // { // counter: 0, // todos: [ 'Use Redux' ] // } 參考資料
|
工作日 8:30-12:00 14:30-18:00
周六及部分節(jié)假日提供值班服務(wù)