理解Javascript的狀態容器Redux

來源:互聯網
上載者:User

標籤:lis   持久化   服務   comm   響應   get   remove   建立   原因   

Redux要解決什麼問題?

隨著 JavaScript 單頁應用開發日趨複雜,JavaScript 需要管理比任何時候都要多的 state (狀態)。 這些 state 可能包括伺服器響應、快取資料、本地產生尚未持久化到伺服器的資料,也包括 UI 狀態,如啟用的路由,被選中的標籤,是否顯示載入動效或者分頁器等等。
管理不斷變化的 state 非常困難。如果一個 model 的變化會引起另一個 model 變化,那麼當 view 變化時,就可能引起對應 model 以及另一個 model 的變化,依次地,可能會引起另一個 view 的變化。直至你搞不清楚到底發生了什麼。state 在什麼時候,由於什麼原因,如何變化已然不受控制。 當系統變得錯綜複雜的時候,想重現問題或者添加新功能就會變得舉步維艱。
Redux的設計借鑒Flux、 Elm、Immutable,它的出現就是為瞭解決state裡的資料問題。Redux和Flux的主要區別是Redux裡面是單一的資料來源設計,而Flux(或者Reflux)裡面有多個資料來源。

Redux是如何工作的?

我們知道,在React中,資料在組件中是單向流動的。資料從一個方向父組件流向子組件(通過props),由於這個特徵,兩個非父子關係的組件(或者稱作兄弟組件)之間的通訊並不是那麼清楚。
React並不建議直接採用組件到組件的通訊方式,儘管它有一些特性可以支援這麼做(比如先將子組件的值傳遞給父組件,然後再由父組件在分發給指定的子組件)。這被很多人認為是糟糕的實踐方式,因為這樣的方式容易出錯而且會讓代碼向“拉麵”一樣不容易理解。
當然React也沒有直接建議如何去處理這種情形,以下是React的文檔中關於這部分的描述:

對於非父子關係的組件,你可以自己建立一個全域的事件系統,Flux的模式也是一種可行的方式。

Redux的出現就讓這個問題的解決變得更加方便了。Redux提供一種儲存整個應用狀態到一個地方的解決方案(可以理解為統一狀態層),稱為“store”,組件將狀態的變化轉寄通知(dispatch)給store,而不是直接通知其它的組件。組件內部依賴的state的變化情況可以通過訂閱store來實現。
使用Redux,所有的組件都從store裡面擷取它們依賴的state,同時也需要將state的變化告知store。組件不需要關注在這個store裡面其它組件的state的變化情況,Redux讓資料流變得更加簡單。這種思想最初來自Flux,它是一種和React相同的單向資料流的設計模式。

Redux的核心設計理念

Redux有三大原則

  • 單一資料來源,整個應用的 state 被儲存在一棵 object tree 中,並且這個 object tree 只存在於唯一一個 store 中
  • State 是唯讀,惟一改變 state 的方法就是觸發 action,action 是一個用於描述已發生事件的普通對象。
  • 使用純函數來執行修改,為了描述 action 如何改變 state tree ,你需要編寫 reducers。

單一資料來源的設計讓React的組件之間的通訊更加方便,同時也便於狀態的統一管理。
根據Redux的文檔,狀態變化的唯一方式是觸發一個action(一個可以描述發生了什麼的對象),這意味著我們不能直接的去修改狀態,取而代之的是我們可以通過轉寄action去告訴store我們有改變狀態的意圖。store對象提供了非常少的API,僅僅只有4個方法:

store.dispatch(action)store.subscribe(listener)store.getState()replaceReducer(nextReducer)

通過這幾個API不難發現,store並沒有直接提供setState()方法。
另外,由於它大量使用 pure function 和 plain object 等概念(reducer 和 action creator 是 pure function,state 和 action 是 plain object)這對於項目的穩定性會是非常好的保證。

理解Action、Reducer

一個action的例子:

var action = {  type: ‘ADD_USER‘,  user: {name: ‘Dan‘}};// 假設store對象已經通過Redux.createStore()建立store.dispatch(action);

這段代碼中,通過dispatch() 方法將action傳遞給了store。Action 本質上是 JavaScript 普通對象。我們約定,action 內必須使用一個字串類型的 type 欄位來表示將要執行的動作。多數情況下,type 會被定義成字串常量。當應用規模越來越大時,建議使用單獨的模組或檔案來存放 action。

import { ADD_TODO, REMOVE_TODO } from ‘../actionTypes‘

前面描述過,Redux不允許直接去改變state,必須通過轉寄action來告訴store有這個意圖要去改變這個狀態。reducer正是扮演處理轉寄過來的action的意圖的函數並且可以改變狀態的角色。一個reducer接受當前的state作為參數,通過返回新的state去改變原有的state:

var someReducer = function(state, action) {  ...  return state;}

由於reducer是純函數,需要注意:

  • 不允許在reducer函數內部進行網路調用或者資料庫查詢操作
  • 不能改變它的參數
    這樣做的好處是:每次調用同樣的一個函數,傳入相同的值可以得到相同的結果。對系統的其它部分也不會產生副作用。
第一個Redux store

使用Redux.createStore()來建立一個store,並且將所有的reducers作為參數傳遞給它,此處以一個reducer為例子:

var userReducer = function(state=[], action) {  if (action.type === ‘ADD_USER‘) {    var newState = state.concat([action.user]);    return newState;  }  return state;}// 建立一個store,並且將reducer作為參數傳遞給它var store = Redux.createStore(userReducer);// 將action傳遞給store,告訴store我們有改變狀態的意向store.dispatch({  type: ‘ADD_USER‘,  user: {name: ‘cpselvis‘}});

上述代碼運行後發生的事情:

  • Store被建立
  • reducer確定初始的state的值是空數組
  • action被轉寄給store
  • reducer將newUser添加到state中,並且將它返回,更新store

通過這段代碼可以發現:reducer函數實際上被執行了2次,一次是store建立的時候,一次是action被轉寄之後。另外需要注意:Redux希望reducer函數總是返回一個新的狀態。這時的結果:

store.getState();  // => [{name: ‘cpselvis‘}]

通過這個例子,可以總結出Redux的工作流程

到這裡,component -> action -> store -> reducer -> state 的單向資料流的問題就講完了。概括的說就是:React組件裡面擷取了資料之後(比如ajax請求),然後建立一個action通知store我有這個想改變state的意圖,然後reducers(一個action可能對應多個reducer,可以理解為action為訂閱的主題,可能有多個訂閱者)來處理這個意圖並且返回新的state,接下來store會收集到所有的reducer的state,最後更新state。

理解Javascript的狀態容器Redux

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.