前言
隨著 JavaScript 單頁應(yīng)用開發(fā)日趨復(fù)雜褒墨,JavaScript 需要管理比任何時候都要多的 state (狀態(tài))。 這些 state 可能包括服務(wù)器響應(yīng)咸这、緩存數(shù)據(jù)、本地生成尚未持久化到服務(wù)器的數(shù)據(jù),也包括 UI 狀態(tài)忆矛,如激活的路由,被選中的標(biāo)簽请垛,是否顯示加載動效或者分頁器等等催训。
管理不斷變化的 state 非常困難,因此宗收,如何優(yōu)雅的管理應(yīng)用中的數(shù)據(jù)狀態(tài)成為了一個需要解決的問題漫拭。
當(dāng)下已有不少優(yōu)秀的狀態(tài)管理工具可以幫助我們解決這一難題,接下來的這段時間混稽,我會選擇現(xiàn)目前比較流行的 Redux 和 Mobx來進(jìn)行學(xué)習(xí)實踐采驻,并將學(xué)習(xí)軌跡記錄于此,便于日后查閱和鞏固匈勋。
本篇文章記錄Redux的一些基礎(chǔ)知識礼旅。
Redux是什么
專注于狀態(tài)管理的庫, 和 React 解耦洽洁。Redux 可以支持 React痘系、Angular、Ember饿自、jQuery 甚至純 JavaScript汰翠。基本中心思想可以描述如下:
(state, action) => newState
Redux核心概念
- state-狀態(tài)樹
例如:
{
todos: [{
text: 'Eat food',
completed: true
}, {
text: 'Exercise',
completed: false
}],
visibilityFilter: 'SHOW_COMPLETED'
}
- Action
Action本質(zhì)上是JavaScript普通對象昭雌,是把數(shù)據(jù)從應(yīng)用傳到 store 的有效載荷复唤。我們約定,action 內(nèi)必須使用一個字符串類型的 type 字段來表示將要執(zhí)行的動作烛卧。除了 type 字段外苟穆,action 對象的結(jié)構(gòu)完全由開發(fā)者自己決定。
{
type: '吃蘋果',
text: '我吃了一個蘋果'
}
- Reducer
Reducer 就是一個純函數(shù),接收舊的 state 和 action雳旅,返回新的 state跟磨。其指定了應(yīng)用狀態(tài)的變化如何響應(yīng) actions 并發(fā)送到 store 的,記住 actions 只是描述了有事情發(fā)生了這一事實攒盈,并沒有描述應(yīng)用如何更新 state抵拘。 - Store
Store 是把action 和 reducers聯(lián)系到一起的對象,有以下職責(zé):
(1)維持應(yīng)用的state型豁;
(2)提供getState()方法獲取state僵蛛;
(3)提供dispatch(action)方法更新state;
(4)通過subscribe(listener)注冊監(jiān)聽器迎变;
(5)通過subscribe(listener)返回的函數(shù)注銷監(jiān)聽器充尉;
簡單的redux應(yīng)用
- 通過reducer新建store,隨時通過store.getState獲取狀態(tài)
- 需要狀態(tài)變更時衣形, 使用store.dispatch(action)來修改狀態(tài)
- Reducer 函數(shù) 接收state 和 action驼侠,返回新的state,可以用store.subscribe監(jiān)聽每次修改
import { createStore } from 'redux'
// reducer谆吴,根據(jù)老的state和action倒源, 返回新的state
const counter = (state={}, action) => {
switch (action.type) {
case '摘蘋果':
return state+1;
break;
case '吃蘋果':
return state-1;
break;
default:
return state;
break;
}
}
// 新建store
const store = createStore(counter)
// 獲取狀態(tài)
const init = store.getState()
console.log(`最初籃子里有${init}個蘋果`) // 最初籃子里有0個蘋果
const listener = () =>{
const current = store.getState()
console.log(`現(xiàn)在籃子里有${current}個蘋果`)
}
// 訂閱listener,每次修改state,都會執(zhí)行l(wèi)istener
const unsubscribe = store.subscribe(listener)
// 使用store.dispatch(action)來修改狀態(tài)
store.dispatch({ type: '摘蘋果'}) // 現(xiàn)在籃子里有1個蘋果
store.dispatch({ type: '摘蘋果'}) // 現(xiàn)在籃子里有2個蘋果
store.dispatch({ type: '吃蘋果'}) // 現(xiàn)在籃子里有1個蘋果
// 停止監(jiān)聽 state 更新
unsubscribe();
補充知識點
function counter(state=0, action) {...}
其中state=0是es6中為函數(shù)參數(shù)指定默認(rèn)值的寫法句狼,即調(diào)用該函數(shù)時笋熬,若不傳對應(yīng)的參數(shù),或傳undefined腻菇, 則使用指定的默認(rèn)值胳螟。
PS: 若有錯誤或不準(zhǔn)確的地方,歡迎指正筹吐!感謝旺隙!