書籍完整目錄javascript
這一節將介紹 React 的核心應用架構模式 Flux,包括內容:前端
Flux 介紹java
MVC 架構之痛git
Flux 的理解github
Flux 相關庫和工具介紹編程
Flux 與 React 實例redux
最後咱們將會把以前的 TODOMVC 改成 Flux 的架構。segmentfault
簡單來說,Flux 是 Facebook 引入到 React 中的一種前端架構,經過定義其核心單向數據流的方式,讓 React 應用更加健壯。同時,這種應用架構也具備普適性,能夠應用到其餘任意前端項目中,甚至能夠應用到客戶端應用開發中,也就是說 Flux 更應該叫作一種架構模式(Pattern)。後端
在詳細介紹 Flux 以前,咱們先來看看傳統的前端 MVC 架構以及其帶來的問題。架構
MVC 的實現可能有不少種方式,比較靈活,但基本本質不會改變,只是三者間的數據傳遞方向可能會改變,即使是 MVP 模式也只是 MVC 的變種,因此爲了統一咱們且如下圖的 MVC 方式來討論。
Model: 負責保存應用數據,和後端交互同步應用數據
View: 負責渲染頁面 HTML DOM
Controller: 負責鏈接 View 和 Model , Model 的任何改變會應用到 View 中,View 的操做會經過 Controller 應用到 Model 中
關係:Model, View, Controller 都是多對多關係。
以 TODOMVC 爲例子用戶添加一個 todo 的交互流程:
View -> Action -> Controller -> Model -> View
View -> Action: 添加按鈕事件或者 input 輸入的提交事件
Action -> Controller: 控制器響應 View 事件
Controller -> Model: 控制器依賴 Model, 調用 Model 添加 todo
Model -> View: View 監聽 Model 的改變添加 todo 事件,在 HTML 中添加一個新的 Todo 視圖
對於新增一個 todo ,須要編寫一個視圖渲染處理函數,函數內添加新項目到列表中。同理對於刪除一個 todo,也會有一個處理函數。當業務邏輯變多事後,可能有不少模型須要作增刪改的功能,與之對應的就是咱們須要精心構建這麼多的渲染處理函數。 這種局部更新模式是高性能的關鍵所在,但問題是:
更新邏輯複雜,須要編寫大量的局部渲染函數
問題定位困難,頁面的當前狀態是有數據和這些局部更新函數肯定的
若是渲染函數只有一個,統一放在 App 控制器中,每次更新重渲染頁面,這樣的話:
任何數據的更新都只用調用重渲染就行
數據和當前頁面的狀態是惟一肯定的
重渲染也有弊端,會帶來嚴重的性能問題,重渲染和局部渲染各有好壞,對 MVC 來講這是一個兩難的選擇,沒法作到魚和熊掌兼得。
那如何才能兼顧兩種模式的優勢?
經過 React + Flux
就能夠完美解決 MVC 的問題。
重渲染: 在 React 中每次渲染都是重渲染,且不影響頁面性能,是由於重渲染的是 Virtual Dom。這就意味着徹底不用去關係重渲染問題,增刪改的渲染都和初始化渲染相同入口
數據和狀態一致性: Store 的數據肯定應用惟一的狀態
簡單來講在 Flux 架構中直接剝離了控制器層,MVC
架構變成了 MV + Flux
架構。
單向數據流
這是 Flux 架構的核心思想,重上面的圖中能夠看到,數據的流向從action 到 view 的一個單向流。
Action
Action 能夠理解爲對應用數據修改的指令,任何修改應用數據的行爲都必須需經過觸發 action 來修改。Action 能夠來自於 View,也能夠來自服務端的數據更新。
Action Creator:
爲了抽象 Action ,提供一些輔助的語義化的方法來建立 Action,這些輔助方法叫作 Action Creator。
Stores
應用的數據中心,全部應用數據都存放在這裏控制,同時包含數據的控制行爲,可能包含多個 store
Dispatcher
action 的控制者,全部 action 都會經過 dispatcher,由 dispatcher 控制 action 是否應該傳入到 store 中,Dispatcher 是一個單例。
View
頁面的視圖,對應 React 的 Component, 視圖能夠觸發 action 到 dispatcher。
須要區別出一種叫控制器 View(Controller View)的類型,這種 View 能夠知曉 store 數據,把 store 數據轉化爲自身的狀態,在將數據傳遞給其餘 view 。 而且能夠監聽 store 數據的改變,當 store 數據改變事後從新設置狀態觸發重渲染。 能夠將控制器 View 對應 MVC 中的控制器,可是差異很大,控制器 View 惟一多作的事情就是監聽 store 數據改變,沒有其餘任何業務處理邏輯。
一樣以 TODOMVC 的添加 todo 爲例,Flux 中的流程爲:
View -> Action(Action Creator -> Action) -> Dispatcher -> Store -> Controller View -> View
View -> Action: 添加按鈕事件或者 input 輸入的提交事件,View 中將事件轉化爲 action, action 由 Action Creator 建立。
Action -> Dispatcher: action 統一由 Dispatcher 分配
Dispatcher -> Store: Dispatcher 分配 action 到 Store
Store -> Controller View: 控制器 View 監聽 store 的數據改變,將數據轉化爲自身屬性
Controller View -> View: 數據改變自動重渲染全部視圖
渲染策略: 數據改變 Flux 自動渲染,MVC 手動編寫更新函數
事件觸發策略: Flux 中全部 action 交給 dispather 分配,MVC 中交給對應的控制器分配
Flux 在覈心策略上的不一樣是解決 MVC 架構問題的關鍵
Flux 架構是很是優雅簡潔的,合理利用了一些優秀的架構思惟
數據的處理過程是 Store -> Controller View -> View
。 全部數據來自於 Store,頁面的渲染層級爲 Store 將數據傳入 Controller View, 再由 Controller View 傳入子 View , 一直到 View 的葉子節點。
這個是一個典型的分而治之策略,將大的頁面拆分爲小的模塊,再由小的模塊拆分爲小的組件,具體組件負者組件自身的問題,全部子組件都是自私的,不用關心「你們」,只用關心「小家」。
Flux 把全部的 View 都視做愚民,Store 視做資源的擁有者爲統治者,統治者須要提供資源(數據)給平民,可是若是平民企圖對資源修改(Mutation),必須得先通知給統治者,讓統治者決定是否作處理。
咱們爲 Flux 中的概念分配角色
View: 平民
Action: 資源修改操做
Dispatcher: 審覈官
Store: 統治者
一個企圖修改資源的操做能夠描述爲:
View Require Mutation -> Action -> Dispatcher -> Store -> Mutate Handler
平民提交 Mutation 請求,由審覈官控制,審覈經過後遞交給統治者,統治者再分配給親信作資源 Mutation
合而治之的策略也等於中心化控制策略, 做爲統治者既要懂得放權利(資源的分配),也要懂得控制權利(資源的修改),這種收縮自如的合理性是 Flux 簡潔的根本。
同時這種思惟帶來的優勢以下:
View 的獨立性和簡單性:View 自身的邏輯簡單,不須要知道太多事情,只關心上級傳來的數據,這種模式使得 View 是低耦合的,簡潔的。
高可維護性:中心化控制知道全部對資源的操做,若是發生 bug, 能夠很快定位問題
在 Flux 中數據的單向流動依賴於 View 的肯定性,相同的數據傳入相同的組件,獲得的結果必然要相同,這是函數式編程的思想。
函數式編程中的純函數(Pure Function)定義以下:
純函數是這樣一種函數,即相同的輸入,永遠會獲得相同的輸出,並且沒有任何可觀察的反作用
如:
// 純函數,相同的輸入一定有相同的輸出 function pure(a, b, c) { return a + b + c; } // 非純函數,咱們永遠沒法肯定 this.a 會變成什麼 function notPure(b, c) { return this.a + b + c; }
爲了保證組件也能作到 「純函數」 的特性,相同的屬性會獲得相同的渲染結果。 在寫 React 組件的時候儘可能準守一下約定:
儘可能使用無狀態組件
除了控制類組件之外其餘組件避免使用組件狀態
能夠經過屬性計算出來的狀態不要用狀態來表示
組件的渲染避免外部依賴,按照純函數的方式寫
函數式的優勢也是無反作用組件的優勢:
無耦合,可移植性強: 組件可重用性高
可測試性高:組件無依賴,能夠很容易的單獨測試組件
上面已經講過 Flux 更應該算是 Facebook 提出的一種前端架構模式,而根據這種理念的 Flux 實現有不少,如下是 github star 數較高的一些實現:
Redux 目前承認度最高的實現
後面咱們會在第四章中專門講解 Redux 與 React 的應用。
@todo