書中的此章節「思想」類成分較多,須要理解的內容也相對較多,若是一一列舉,本文就寫的相對繁瑣了,推薦有興趣的同窗能夠去看一下書籍以及敲一下書中的代碼,有助於理解做者大牛的思想,我就在此簡略的記錄一些相對重要的「點」了。html
1、Flux框架的誕生以及解決了MVC框架哪些問題前端
一、Flux出現背景npm
Facebook的工程部門發如今前端使用MVC框架進行邏輯劃分時,在業務量和代碼量龐大的狀況下,model層和view層之間依賴過於複雜,不利於後期對於代碼的維護瀏覽器
理想中,各個模塊分工:框架
Model:負責邏輯以及數據函數
View:負責渲染界面this
Controller:負責接收用戶的輸入,根據用戶的輸入調用對應的Model部分邏輯,把產生的數據結果交給View部分,讓View渲染出必要的輸出spa
MVC框架的請求流程:用戶請求------>Controller------>Model------>View,View和Model不能直接進行互相通訊,都須要藉助於Controlprototype
在實際工做中,對於瀏覽器端 MVC 框架,存在用戶的交互處理,界面渲染出來以後,Model 和 View 依然存在於瀏覽器中,這時候就會誘惑開發者爲了簡便,讓現存的 Model和 View直接對話,當代碼量和邏輯複雜時,使程序「脆弱並且不可預測」3d
二、Flux框架
(1)特色:更嚴格的數據流控制
(2)各個模塊:
Dispatcher(至關於「Controller」):用來接收Actions、執行回調函數;
Store(至關於「Model」):用來存放應用的狀態,一旦發生變更,就提醒Views要更新頁面;
Action(至關於「用戶請求」):視圖層發出的消息;
View:顯示用戶界面;
(3)與MVC框架的區別:
(i)當系統須要擴充應用所能處理的「請求」時,在MVC中,經過在Controller增長函數,來實現擴充;
在Flux中,不須要Dispatcher增長新函數,而是經過增長新的Action類型,來實現擴充
(4)Flux實踐 (直接上代碼)
實現的效果:
當點擊「+」按鈕或者「-」按鈕,對應行的數字會時時進行改變,而且總數也會時時改變,下圖:
步驟一
安裝Flux:npm install --save flux (若是感受慢,能夠安裝國內淘寶鏡像)
(i)Dispatcher
做用:生成Dispatcher實例,用來以後將 Action 派發到 Store
注意!注意! 注意!Dispatcher實例在全局只有一個
(ii)Action(分2個文件,一個定義action類型,另外一個定義action構造函數)
ActionTypes.js
說明:將常量放在單獨一個文件方便管理
Actions.js
做用:根據類型,生成不一樣的action對象,經過Dispatcher實例的dispatch函數派發出去
注意:出於業界習慣,這個文件被命名爲Actions.js,可是要注意裏面定義的並非action對象自己,而是可以產生並進行派發action對象的函數
(iii)Store(建立了兩個store,CounterStore是爲Counter組件服務,SummaryStore是爲總數服務)
CounterStore.js
說明:在CounterStore中能夠看出,首先定義了Counter組件初始化的值,而後使用Object.assgin()函數,對EventEmitter.prototype對象進行了淺拷貝,並在此淺拷貝對象的基礎上擴充了getCounterValues、emitChange、addChangeListener、removeChangeListener方法。其中這四個方法的後三個方法,分別調用了EventEmitter.prototype的on(),emit(),removeListener()方法,做用以下:
on(EVENT_TYPE,callback):用來監聽事件,第一個參數是字符串事件類型,第二個參數是事件處理函數;
emit(EVENT_TYPE):用來觸發事件,第一個參數是字符串事件類型;
removeListener(EVENT_TYPE,callback):用來移除事件,若是要調用removeListener函數,就必定要保留對處理函數的引用,
第一個參數是字符串事件類型,第二個參數是事件處理函數。
最後,經過把AppDispatcher.register()中的回調函數註冊到Dispatcher上,來接受以前經過AppDispatcher.dispatch()派發的action對象,經過switch或if-else來實現對應類型的動做實現對應類型的操做。
SummaryStore.js
說明:整體代碼和以前CounterStore差很少。須要說明的是在這兩個store中,AppDispatcher.register()會返回一個標記,保存在各自store的dispatchToken字段中,用來以後實現多個store之間行爲的依賴順序,藉助waitFor()。在這個代碼中,咱們但願SummaryStore的邏輯在CounterStore以後進行
做用: Store是一個對象,既用於存儲應用狀態,也用來接受Dispatcher派發的動做,根據動做決定是否更新應用狀態。
注意:store 在Flux中能夠存在多個,每個 store 都會受到全部的 action 通知,而後自行以爲是否對這個 action 作出響應,更新 state;
store對外只暴露了讀取接口,若是想實現寫入的功能,只能去實現對應action。
(iv)View(用React進行實現,3個視圖組件,其中ControlPanel父組件包含Counter子組件,Summary子組件)
ControlPanel組件
Counter
Summary
View 的代碼就是常規React書寫方式,就不一一敘述了
注意:存在於Flux框架中的React組件須要實現如下幾個功能
1)建立時要讀取Store上的狀態來初始化組件內部狀態;(而不像以前經過props傳參,實現組件內部初始化)
2)當Store上狀態發生變化時,組件要馬上同步更新內部狀態保持一致;(經過Store改變狀態後調用emit(),以及View經過on()來監聽Store中狀態的變化)
3)View若是要改變Store狀態,只能派發action。(Flux中,對Store進行修改,只能經過新建action)
(v)上述代碼我的理解及總結:
過程一:按着組件的生命週期函數順序,進行渲染。其中componentDidMount函數經過CounterStore.addChangeListen函數監聽了CounterStore的變化以後,只要CounterStore發生變化,Counter組件的onChange函數就自動會被調用。不過首次掛載時,能夠發現getCounterValue被重複調用了2次來讀取相同值,分別是第一個是constructor中被調用,第二個是componentDidMount中的this.onChange中被調用
過程二:當進行點擊「+」按鈕時,this.props.caption當即讀取了當前組件上的屬性值First,以形參的形式傳入increment()方法,並觸發increment();
(以First爲例子)
過程三:此時Dispatcher的實例(AppDispatcher)調用dispatch()方法,將剛產生的action對象派發出去,此時action對象上攜帶着動做類型,以及剛剛傳入的First字符串標記
過程四: 經過AppDispatche.register()來註冊回調函數,以後這個回調函數就能夠接受派發出來的action對象,並根據這個action對象的類型,執行對應的邏輯,即在這裏的邏輯是根據action.counterCaption拿到First,而後經過counterValues[First]拿到當前保存在Store中的初始值,並進行加一操做,最後經過emit(),將事件觸發
過程五:在過程一首次掛載時,onChange函數做爲形參數,最終傳入on()中,監聽事件的觸發,也就是等待emit函數被調用,而後執行onChange函數內部操做,經過getCounterValues得到Store的新狀態值,即First字段加一後的值,最後經過setState函數將這個值同步到組件內部狀態count上,同時State的更新會觸發生命週期的shouldComponentUpdate函數,判斷這次渲染是否與上一次不一樣,若是不一樣則返回true,並將結果渲染到頁面
其餘的「-」按鈕以及計算總和的步驟流程也差很少,我就不繼續進行描述了,能夠按照上面過程進行推演。
結合本身理解,畫了一個圖,完畢。
三、Flux框架的優勢:
(1)對比純粹使用React框架,當多個組件或者組件之間多層嵌套的狀況下,對一個全局變量進行操做,只經過props進行操做顯的特別的麻煩,
在使用Flux框架狀況下,React組件在其中只充當了View並對Store進行了時時的監聽,全局變量由Store進行保存,組件能夠經過action對Store進行操做,並反饋到View。
避免的props帶來的繁瑣,不過程序若是不復雜,使用Flux也可能把「簡單問題複雜化」,使用時視狀況而定。
(2)對比前端MVC框架,他的「單向數據流」管理方式更加的嚴格。
四、Flux框架不足:
(1) 多個Store之間的依賴
(2) Store混雜邏輯和狀態
睡覺睡覺!!!!!!!未完待續~~~