(一)狀態(tài)管理工具之Redux-基礎(chǔ)篇

前言

隨著 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è)器等等。
管理不斷變化的 state 非常困難,因此,如何優(yōu)雅的管理應(yīng)用中的數(shù)據(jù)狀態(tài)成為了一個(gè)需要解決的問(wèn)題。
當(dāng)下已有不少優(yōu)秀的狀態(tài)管理工具可以幫助我們解決這一難題,接下來(lái)的這段時(shí)間,我會(huì)選擇現(xiàn)目前比較流行的 Redux 和 Mobx來(lái)進(jìn)行學(xué)習(xí)實(shí)踐,并將學(xué)習(xí)軌跡記錄于此,便于日后查閱和鞏固。
本篇文章記錄Redux的一些基礎(chǔ)知識(shí)。

Redux是什么

專注于狀態(tài)管理的庫(kù), 和 React 解耦。Redux 可以支持 React、Angular、Ember、jQuery 甚至純 JavaScript?;局行乃枷肟梢悦枋鋈缦拢?/p>

(state, action) => newState

Redux核心概念

  • state-狀態(tài)樹(shù)
    例如:
{
  todos: [{
    text: 'Eat food',
    completed: true
  }, {
    text: 'Exercise',
    completed: false
  }],
  visibilityFilter: 'SHOW_COMPLETED'
}

  • Action
    Action本質(zhì)上是JavaScript普通對(duì)象,是把數(shù)據(jù)從應(yīng)用傳到 store 的有效載荷。我們約定,action 內(nèi)必須使用一個(gè)字符串類型的 type 字段來(lái)表示將要執(zhí)行的動(dòng)作。除了 type 字段外,action 對(duì)象的結(jié)構(gòu)完全由開(kāi)發(fā)者自己決定。
{
  type: '吃蘋果',
  text: '我吃了一個(gè)蘋果'
}
  • Reducer
    Reducer 就是一個(gè)純函數(shù),接收舊的 state 和 action,返回新的 state。其指定了應(yīng)用狀態(tài)的變化如何響應(yīng) actions 并發(fā)送到 store 的,記住 actions 只是描述了有事情發(fā)生了這一事實(shí),并沒(méi)有描述應(yīng)用如何更新 state。
  • Store
    Store 是把a(bǔ)ction 和 reducers聯(lián)系到一起的對(duì)象,有以下職責(zé):
    (1)維持應(yīng)用的state;
    (2)提供getState()方法獲取state;
    (3)提供dispatch(action)方法更新state;
    (4)通過(guò)subscribe(listener)注冊(cè)監(jiān)聽(tīng)器;
    (5)通過(guò)subscribe(listener)返回的函數(shù)注銷監(jiān)聽(tīng)器;

簡(jiǎn)單的redux應(yīng)用

  • 通過(guò)reducer新建store,隨時(shí)通過(guò)store.getState獲取狀態(tài)
  • 需要狀態(tài)變更時(shí), 使用store.dispatch(action)來(lái)修改狀態(tài)
  • Reducer 函數(shù) 接收state 和 action,返回新的state,可以用store.subscribe監(jiān)聽(tīng)每次修改
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}個(gè)蘋果`)     // 最初籃子里有0個(gè)蘋果

const listener = () =>{
  const current = store.getState()
  console.log(`現(xiàn)在籃子里有${current}個(gè)蘋果`)
}
// 訂閱listener,每次修改state,都會(huì)執(zhí)行l(wèi)istener
const unsubscribe = store.subscribe(listener)

// 使用store.dispatch(action)來(lái)修改狀態(tài)
store.dispatch({ type: '摘蘋果'})    // 現(xiàn)在籃子里有1個(gè)蘋果
store.dispatch({ type: '摘蘋果'})    // 現(xiàn)在籃子里有2個(gè)蘋果
store.dispatch({ type: '吃蘋果'})    // 現(xiàn)在籃子里有1個(gè)蘋果
 // 停止監(jiān)聽(tīng) state 更新
unsubscribe();

補(bǔ)充知識(shí)點(diǎn)

function counter(state=0, action) {...}

其中state=0是es6中為函數(shù)參數(shù)指定默認(rèn)值的寫法,即調(diào)用該函數(shù)時(shí),若不傳對(duì)應(yīng)的參數(shù),或傳undefined, 則使用指定的默認(rèn)值。
PS: 若有錯(cuò)誤或不準(zhǔn)確的地方,歡迎指正!感謝!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容