React
React 是一個 View 層的框架,用來渲染視圖,它主要做幾件事情:
組件化
利用 props 形成單向的數(shù)據(jù)流
根據(jù) state 的變化來更新 view
利用虛擬 DOM 來提升渲染性能
前面說到 React 能夠根據(jù) state 的變化來更新 view,一般來說引起 state 變化的動作除了來自外部(如服務(wù)器),大部分都來自于頁面上的用戶活動,那頁面上的用戶活動怎樣對 state 產(chǎn)生作用呢?React 中每個組件都有 setState 方法用于改變組件當(dāng)前的 state,所以可以把更改 state 的邏輯寫在各自的組件里,但這樣做的問題在于,當(dāng)項目邏輯變得越來越復(fù)雜的時候,將很難理清 state 跟 view 之間的對應(yīng)關(guān)系(一個 state 的變化可能引起多個 view 的變化,一個 view 上面觸發(fā)的事件可能引起多個 state 的改變)。我們需要對所有引起 state 變化的情況進行統(tǒng)一管理,于是就有了 Flux。
Flux
Flux 是一種應(yīng)用架構(gòu),或者說是一種思想,它跟 React 本身沒什么關(guān)系,它可以用在 React 上,也可以用在別的框架上。前面說到 Flux 在 React 中主要用來統(tǒng)一管理引起 state 變化的情況。Flux 維護著一個或者多個叫做Store的變量,就像 MVC 里面的 Model,里面存放著應(yīng)用用到的所有數(shù)據(jù),當(dāng)一個事件觸發(fā)時 ,F(xiàn)lux 對事件進行處理,對 Store 進行更新,當(dāng) Store 發(fā)生變化時,通常是由應(yīng)用的根組件(也叫 controller view)去獲取最新的 store,然后更新 state,之后利用 React 單向數(shù)據(jù)流的特點一層層將新的 state 向下傳遞實現(xiàn) view 的更新。這里的 controller view 可以有多個也可以不是根組件,但是這樣數(shù)據(jù)流維護起來就比較麻煩。
Flux 的思維模型如下:
Flux 主要包括四個部分,Dispatcher、Store、View、Action,其中 Dispatcher 是 Flux 的核心樞紐,它相當(dāng)于是一個事件分發(fā)器,將那些分散在各個組件里面的邏輯代碼收集起來,統(tǒng)一在 Dispatcher 中進行處理。完整的 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() 方法,重新渲染自身以及組件樹上的所有后代組件。使用 Flux 有個好處就是我只需要用 action 對象向 Dispatcher 描述當(dāng)前的事件就可以執(zhí)行對應(yīng)的邏輯,因為 Dispatcher 是所有 Action 的處理中心,即使沒有對應(yīng)的事件發(fā)生,我們也可以“偽造”一個出來,非常利于測試。
Redux
Redux 的作用跟 Flux 是一樣的,它可以看作是 Flux 的一種實現(xiàn),但是又有點不同,具體的不同總結(jié)起來就是:
1. Redux 只有一個 store,Flux 里面會有多個 store 存儲應(yīng)用數(shù)據(jù),并在 store 里面執(zhí)行更新邏輯,當(dāng) store 變化的時候再通知 controller-view 更新自己的數(shù)據(jù),Redux 將各個 store 整合成一個完整的 store,并且可以根據(jù)這個 store 推導(dǎo)出應(yīng)用完整的 state。同時 Redux 中更新的邏輯也不在 store 中執(zhí)行而是放在 reducer 中。2. 沒有 DispatcherRedux 中沒有 Dispatcher 的概念,它使用 reducer 來進行事件的處理,reducer 是一個純函數(shù),這個函數(shù)被表述為(previousState, action) => newState,它根據(jù)應(yīng)用的狀態(tài)和當(dāng)前的 action 推導(dǎo)出新的 state。Redux 中有多個 reducer,每個 reducer 負責(zé)維護應(yīng)用整體 state 樹中的某一部分,多個 reducer 可以通過combineReducers方法合成一個根reducer,這個根reducer負責(zé)維護完整的 state,當(dāng)一個 action 被發(fā)出,store 會調(diào)用 dispatch 方法向某個特定的 reducer 傳遞該 action,reducer 收到 action 之后執(zhí)行對應(yīng)的更新邏輯然后返回一個新的 state,state 的更新最終會傳遞到根reducer處,返回一個全新的完整的 state,然后傳遞給 view。
在我看來,Redux 和 Flux 之間最大的區(qū)別就是對 store/reducer 的抽象,F(xiàn)lux 中 store 是各自為戰(zhàn)的,每個 store 只對對應(yīng)的 controller-view 負責(zé),每次更新都只通知對應(yīng)的 controller-view;而 Redux 中各子 reducer 都是由根reducer統(tǒng)一管理的,每個子reducer的變化都要經(jīng)過根reducer的整合。用圖表示的話可以像這樣:
Flux 中的 store 是這樣的:
Redux 中的 store(或者叫 reducer)是這樣的: