ReactJS &Flux &Redux 的設計思想與關係

前言:

在WEB1.0時代,數據改變與頁面刷新的機制比較簡單粗暴:「後端改變state,前端整個頁面view刷新」;前端

web2.0時代,咱們但願:react

「改變state,view自動更新」web

虛擬DOM

瀏覽器裏的DOM tree克隆一份完整的鏡像到內存,也就是所謂的「virtual DOM」,編程

當頁面的state發生變化之後,根據最新的state從新生成一份virtual DOM(至關於在內存裏「刷新」整個頁面),將它和以前的virtual DOM作比對(diff),而後在瀏覽器裏只渲染被改變的那部份內容,這樣瀏覽器的性能損耗和用戶體驗不就都不成問題了嗎?redux

**在絕大多數的WEB開發中:**js引擎的性能和內存徹底沒有被充分利用,咱們正好能夠火力全開,利用js的這部分性能紅利,實現內存中virtual DOM的diff工做,完美!後端

ReactJS:

  • react很是具備表達力的jsx語法和完善的模塊化結構,設計模式

  • view的組件化和模塊化很是有利於分工協做、代碼的積累複用以及單元測試,瀏覽器

伴隨着reactJS 前端框架的崛起,redux這些專一於管理state的輕量級框架橫空出世;bash

*因爲React的「state-view」模式可讓開發者的大腦獲得一種「單向流」的溫馨體驗。那爲何單向流的思惟狀態更加溫馨呢?前端框架

這是由於在單向流狀態下,要解決的問題如同一個函數映射,已知什麼(好比state)是固定不變的,要獲得什麼(好比view)是定義明確,而人的思惟很是習慣於這種定義明確的、沒有「分叉」和「環路」的函數式問題。

頁面呈現的state能夠經過模塊屬性(props)從父模塊傳遞到子模塊。這種"樹狀"分流機制,有點像植物將營養(state)從根部不斷運輸到細枝末葉的過程*

Flux思想:

  • flux 與 react 是徹底獨立的概念,咩有直接的關係;
  • flux 不是JS庫,而是一種前端代碼的組織思想;=>redux 庫能夠認爲是flux 思想的實現;
  • flux 的核心思想和代碼實現雖然很簡單,可是在model(view)-view 開發模式中,起着很是重要的做用;
  • mvc設計思想: MVC開發模式, 主要講的是在開發交互應用時,怎樣將不一樣功能的代碼拆分到不一樣文件或區塊,以便下降代碼的耦合度,提升代碼的可讀性和健壯性。 簡單理解就是:要將 Model-View-Controller 這三部分代碼拆分到不一樣文件。當開發小型的web應用的時候,mvc能夠應付;可是當中大型應用的時候,多model,多view的時候,model-view的‘單向流’被破壞帶來的混亂,帶來難以接受的局面;這種設計模式的model-view關係;facebook團隊總結說:MVC模式難以scale up

flux設計模式就是解決以上model-view混亂=>

flux 設計思想的誕生

如今咱們又能夠從服務器端的MVC模式中得到靈感了!

由於咱們注意到,服務器端的controller一般也須要對不少Model產生修改,但在代碼結構中卻集中在一塊兒,沒有散落一地。緣由很簡單:

  • 因爲server和client是遠程通訊的關係,所以爲了儘可能減小通訊耦合,client每一個操做的所有信息都以http請求的形式被歸納成了精簡的「做用量」(action)。
  • 請求的url路徑約定了用戶的操做意圖(固然RESTful概念中,請求的method也能夠反映操做意圖),request參數表徵了該「意圖」的具體內容。正是基於這個action的抽象,client端的交互操做才能夠被集中轉移到server端的controller中作統一響應。

對比之下,咱們馬上發現上述代碼片段中前端MVC模式的「痛點」所在:不是MVC模式錯了,而是咱們壓根缺乏了一個和用戶交互行爲有關的action抽象!所以,對model的具體操做才無法從各個view組件中被剝離出來,放到一處。

參考http請求,咱們將要定義的action,須要一個typeName用來表示對model操做的意圖(相似於http請求的url路徑),還可能須要其餘字段,用來描述怎樣具體操做model(相似於http請求的參數)。

也就是說,當用戶在view上的交互行爲(例如點擊提交按鈕)應當引發Model發生變化時,咱們不直接修改model,而是簡單地dispatch一個action(其實跟常見的event機制沒有什麼區別)以表達修改model的意圖,這些action將被集中轉移給數據端(models),而後數據端會根據這些action作出須要的自我更新。同時,咱們考慮到react中view組件的樹狀分流結構,因此有以下圖所示:

圖中A表示Action,V表示View組件,Models部分的結構會進一步討論。

稍微總結一下:從代碼層面而言,flux無非就是一個常見的event dispatcher,其目的是要將以往MVC中各個View組件內的controller代碼片段提取出來放到更加恰當的地方進行集中化管理,並從開發體驗上實現了溫馨清爽、容易駕馭的「單向流」模式。 因此我以爲,Flux與其說是對前端MVC模式的顛覆,倒不如說是對前端MVC思想的補充和優化。

但爲了區分於以往的MVC模式,並向facebook的貢獻表達敬意,後面咱們將把這種優化後的 Model-View-Controller 開發模式在React背景下正式稱爲Flux模式

問題:

React的能夠經過View Component把頁面呈現進行「原子化」拆分(即上圖中蘭色區域的樹狀分流結構);

Flux打通了State-View的任督二脈(綠色區域),並經過action抽象把用戶交互行爲
進行了「原子化」拆分;

複製代碼

那麼聯繫上面的圖示,咱們天然要問數據端(紫色區域)的處理,能否一樣被「原子化」拆分?

redux登場 (數據端的「原子化」)

redux 中的reduce機制,將state端的數據處理進行‘原子化’拆分。redux是來自函數式編程(Functional Programming)的一朵奇葩,聽說頗有背景([參考連接](Prior Art | Redux) ) reducer,從代碼上說,其實就是一個函數,具備以下形式:

(previousState, action) => newState
複製代碼

reducer做爲一個函數,能夠根據web應用以前的狀態(previousState)和交互行爲(經過flux中提到的action來表徵),決定web應用的下一狀態(newState),從而實現state端的數據更新處理。這個函數行爲和大名鼎鼎的「Map-Reduce」概念中的Reduce操做很是相似,於是稱這個函數爲「Reducer」。

"shut up and show me the code" redux.js.org/basics/exam…

這裏不打算詳細講解Redux的具體使用,而只想經過一個Redux對state數據進行操做的代碼片段,管窺一下reducer機制對數據進行拆分和組裝的簡潔過程。代碼片段以下

其中的todos是和任務列表數據相關的reducer,todo是和單條任務數據有關的reducer。注意:在todos的函數體內調用了todo,並將action做爲參數原樣傳遞給了todo,這種乾淨利落地經過函數調用將action由 「parent reducer」 傳遞給 「child reducer」,是redux實現數據處理拆分的廣泛方式。

回味一下,咱們應該能夠體會到,這種數據處理「原子化」拆分的方式和react中view組件的拆分有殊途同歸之妙,兩者都會造成一種「樹狀」分流結構(在react的view hierarchy中,數據經過props的直接賦值實現單向流;在redux的reducer hierarchy中,數據經過action的函數傳參實現單向流)。

visibilityFilter是和列表顯示狀態相關的另外一個reducer;combineReducers將visibilityFilter和todos合併爲整個應用的reducer,也就是todoApp。這個過程,從感受上也和react中view組件的合併過程很是相像。

createStore是一個工廠函數。經過它,todoApp(至關於一個數據處理的引擎)被裝配到整個應用的state容器,也就是store中。能夠經過store的getState方法獲取整個應用的state;同時,store也是一個event dispatcher,能夠經過其dispatch和subscribe方法,分別實現觸發action事件和註冊對action事件的響應函數。總言之,從概念上來講 Redux = Reducer + Flux

總結:

全體亮相

如今React開發模式中的幾個核心概念已經所有出場亮相。咱們俯瞰一下整個開發流程:首先,react框架爲咱們理順了 store --> view 的「單向」工做流(store是state的容器);而後,redux框架爲咱們理順了 view --> store 的**「單向」**工做流。而且,react和redux都以組件化的形式能夠將各自負責的功能進行靈活地組裝或拆分,最大程度上確保咱們「一次只須要專一於一個局部問題」。具體來講,分爲如下步驟:

1.單例store的數據在react中能夠經過view組件的屬性(props)不斷由父模塊**「單向」**傳遞給子模塊,造成一個樹狀分流結構。若是咱們把redux比做整個應用的「心肺」 (redux的flux功能像心臟,reducer功能像肺部毛細血管),那麼這個過程能夠比做心臟(store)將氧分子(數據)經過動脈毛細血管(props)送到各個器官組織(view組件)

2.末端的view組件,又能夠經過flux機制,將攜帶交互意圖信息的action反饋給store。這個過程有點像將攜帶代謝產物的「紅細胞」(action)經過靜脈毛細血管又泵迴心髒(store)

3.action流回到store之後,action以參數的形式又被分流到各個具體的reducer組件中,這些reducer一樣構成一個樹狀的hierarchy。這個過程像靜脈血中的紅細胞(action)被運輸到肺部毛細血管(reducer組件)

4.接收到action後,各個child reducer以返回值的形式,將最新的state返回給parent reducer,最終確保整個單例store的全部數據是最新的。這個過程能夠比做肺部毛細血管的血液充氧後,又被從新泵回了心臟

5.回到步驟1

用圖示的方式表達:

  • 圖中A表示Action,V表示View組件,R表示Reducer。

  • 爲了確保咱們比較容易理解程序的全局行爲,或者說提升程序行爲的肯定性(predictable),咱們通常指望具備相似職能的代碼片段被「平鋪」着擺放在一。

  • 所以圖示中相同顏色區域的代碼一般會被放到同一個文件夾/文件中。

  • 另外,一樣出於提升程序的肯定性,redux所遵循的函數式編程鼓勵咱們使用pure function和immutable。

參考: www.cnblogs.com/dreamingbao…

相關文章
相關標籤/搜索