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