小程序模板網(wǎng)

擴(kuò)展微信小程序框架功能:Redux

發(fā)布時(shí)間:2018-04-14 14:47 所屬欄目:小程序開(kāi)發(fā)教程

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 的三大原則中:

  • 單一數(shù)據(jù)源。整個(gè)應(yīng)用的 state 被儲(chǔ)存在一棵 object tree 中,并且這個(gè) object tree 只存在于唯一一個(gè) store 中。
  • State 是只讀的。唯一改變 state 的方法就是觸發(fā) action,action 是一個(gè)用于描述已發(fā)生事件的普通對(duì)象。
  • 使用純函數(shù)來(lái)執(zhí)行修改。為了描述 action 如何改變 state tree ,你需要編寫(xiě) reducers。

Redux 主要分為三個(gè)部分 Action、Reducer、及 Store

  • Action。Action 很簡(jiǎn)單,就是一個(gè)單純的包含 { type, payload } 的對(duì)象,type 是一個(gè)常量用來(lái)標(biāo)示動(dòng)作類(lèi)型,payload 是這個(gè)動(dòng)作攜帶的數(shù)據(jù)。Action 需要通過(guò) store.dispatch() 方法來(lái)發(fā)送。
  • Reducer。Reducer 用來(lái)處理 Action 觸發(fā)的對(duì)狀態(tài)樹(shù)的更改。所以一個(gè) reducer 函數(shù)會(huì)接受 oldState 和 action 兩個(gè)參數(shù),返回一個(gè)新的 state:(oldState, action) => newState。
  • Store。Store 的作用就是連接Action 和 Reducer,Store 的作用有這么幾個(gè):Hold 住整個(gè)應(yīng)用的 State 狀態(tài)樹(shù);提供一個(gè) getState() 方法獲取 State;提供一個(gè) dispatch() 方法發(fā)送 action 更改 State;提供一個(gè) subscribe() 方法注冊(cè)回調(diào)函數(shù)監(jiān)聽(tīng) State 的更改

嚴(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è)步驟:

  • 調(diào)用 store.dispatch(action)。
  • Redux store 調(diào)用傳入的 reducer 函數(shù)。
  • 根 reducer 應(yīng)該把多個(gè)子 reducer 輸出合并成一個(gè)單一的 state 樹(shù)。
  • Redux store 保存了根 reducer 返回的完整 state 樹(shù)。

Redux 與 Flux

Flux 是一種應(yīng)用架構(gòu),或者說(shuō)是一種思想,它跟 React 本身沒(méi)什么關(guān)系,它可以用在 React 上,也可以用在別的框架上。


Flux 主要包括四個(gè)部分,Dispatcher、Store、View、Action,其中 Dispatcher 是 Flux 的核心樞紐,它相當(dāng)于是一個(gè)事件分發(fā)器,將那些分散在各個(gè)組件里面的邏輯代碼收集起來(lái),統(tǒng)一在 Dispatcher 中進(jìn)行處理。

完整的 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 只有一個(gè) store。 Flux 里面會(huì)有多個(gè) store 存儲(chǔ)應(yīng)用數(shù)據(jù),并在 store 里面執(zhí)行更新邏輯,當(dāng) store 變化的時(shí)候再通知 controller-view 更新自己的數(shù)據(jù),Redux 將各個(gè) store 整合成一個(gè)完整的 store,并且可以根據(jù)這個(gè) store 推導(dǎo)出應(yīng)用完整的 state。同時(shí) Redux 中更新的邏輯也不在 store 中執(zhí)行而是放在 reducer 中。
  • Redux 沒(méi)有 Dispatcher。Redux 中沒(méi)有 Dispatcher 的概念,它使用 reducer 來(lái)進(jìn)行事件的處理,reducer 是一個(gè)純函數(shù),這個(gè)函數(shù)被表述為 (previousState, action) => newState,它根據(jù)應(yīng)用的狀態(tài)和當(dāng)前的 action 推導(dǎo)出新的 state。Redux 中有多個(gè) reducer,每個(gè) reducer 負(fù)責(zé)維護(hù)應(yīng)用整體 state 樹(shù)中的某一部分,多個(gè) reducer 可以通過(guò) combineReducers 方法合成一個(gè)根reducer,這個(gè)根reducer負(fù)責(zé)維護(hù)完整的 state,當(dāng)一個(gè) action 被發(fā)出,store 會(huì)調(diào)用 dispatch 方法向某個(gè)特定的 reducer 傳遞該 action,reducer 收到 action 之后執(zhí)行對(duì)應(yīng)的更新邏輯然后返回一個(gè)新的 state,state 的更新最終會(huì)傳遞到根reducer處,返回一個(gè)全新的完整的 state,然后傳遞給 view。

Redux使用

應(yīng)用中所有的 state 都以一個(gè)對(duì)象樹(shù)的形式儲(chǔ)存在一個(gè)單一的 store 中。唯一改變 state 的辦法是觸發(fā) action,一個(gè)描述發(fā)生什么的對(duì)象。
為了描述 action 如何改變 state 樹(shù),需要編寫(xiě) reducers。

    // 這是一個(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' ]
    // }

參考資料

  • Redux
  • Redux@github
  • Redux 中文文檔
  • 微信小程序集成 Redux
  • 解讀redux工作原理
  • 淺談 React、Flux 與 Redux
  • Redux 卍解


易優(yōu)小程序(企業(yè)版)+靈活api+前后代碼開(kāi)源 碼云倉(cāng)庫(kù):starfork
本文地址:http://22321a.com/wxmini/doc/course/23384.html 復(fù)制鏈接 如需定制請(qǐng)聯(lián)系易優(yōu)客服咨詢:800182392 點(diǎn)擊咨詢
QQ在線咨詢