本文是『horseshoe·Redux專題』系列文章之一,後續會有更多專題推出
來個人 GitHub repo 閱讀完整的專題文章
來個人 我的博客 得到無與倫比的閱讀體驗
React的橫空出世給前端帶來一場革命。其實隨React一同開源的還有一個叫Flux的東西。Flux是管理應用狀態的一種架構。光憑一個props是沒法實現血緣關係疏遠的組件之間的狀態同步的。雖然context加回調能夠勉強作到這一點,可是Flux架構有其更加深遠的意義。前端
你看,從一開始facebook的工程師就知道只憑React沒法支撐大型的應用開發。可是爲何稱Flux爲一種架構而不是一個類庫或者框架呢?由於它的出現主要是爲了提出一種思想,而不是做爲一個真正成熟的類庫。facebook的工程師但願社區根據這種思想涌現出多樣化的實現方式。git
那麼,Flux提出的思想是什麼呢?github
這一切還要從MVC架構提及。編程
之前端舉例,MVC架構將一個應用分爲Model
、View
和 Controller
三部分。Model
表明數據模型,用來存放業務邏輯;View
表明視圖,是最終的界面效果;Controller
表明控制器,響應用戶的操做。redux
一個用戶操做View
發出指令,Controller
處理該指令而且將處理結果傳遞給Model
,Model
再將更新後的數據渲染到View
上。架構
當一個應用愈來愈複雜時,如何去維護龐大的代碼和讓新人快速的上手就變的緊迫起來。MVC架構的分層思想就是服務於這一目的,它並不能讓應用的性能提高,可是它可讓代碼對開發者更友好。不過影響代碼對開發者友好度的可不止這一點,更重要的是數據的流向在開發者面前的清晰度。框架
MVC架構有沒有對數據的流向作很好的控制呢?並無。它有一套理想中的流程,就是上面講到的視圖更新的操做過程,然而View
可不能夠直接給Model
發指令?固然能夠,而且不少開發者就是這麼作的。若是每一層均可以和每一層通訊,代碼的可讀性將變的混亂不堪。函數式編程
Flux就是爲解決這個問題而生的。MVC架構的問題在於沒有嚴格控制數據的流向,因此facebook的工程師將Flux設計成數據只能走單通道,一個特定的操做才能觸發另外一個特定的操做。函數
一個Flux應用包含四部分:性能
Action
,一個動做對象,至關於用戶的指令。Dispatcher
,處理動做的派發,至關於MVC架構的Controller
。Store
,負責存儲數據,至關於MVC架構的Model
。View
,和MVC架構同樣。用戶觸發View
上的事件發送Action
,Action
只能經過Dispatcher.dispatch
方法發送出去,Store
更新自身的數據而後View
根據Store
從新渲染。一環扣一環,只能按照這個流程走下去。
這就是咱們說的單向數據流。
至此,咱們實現了功能的分層和數據的單向流動,代碼再也不那麼混亂了。
咱們的主角是Redux,它也是目前React社區最受歡迎的狀態管理框架。實際上,Redux就是Flux的門徒之一。它如此受歡迎,必定是由於它在Flux的基礎上作對了什麼事情。
Flux解決了單向數據流的問題,那麼Redux解決了什麼問題呢?
我認爲Redux的貢獻主要是這兩點:
狀態只讀
和只能經過純函數來改變狀態
都是函數式編程的特性,目的就是爲了改變狀態的過程當中不產生反作用。我們先來講說惟一數據源是怎麼回事?
Flux的設計是將每一塊相對獨立的狀態分別用一個Store來存儲。這樣的好處是顯而易見的,每個Store的體積都足夠小,對象的嵌套不會很深。
壞處是什麼呢?
Dispatcher在派發動做的時候,會依次訪問每個Store。這樣雖然會損失一些性能,可是Dispatcher的邏輯能夠作到極簡,它不用知道這個動做應該派發給誰,都給它們發一遍得了。假如Store A對Store B存在依賴關係,那麼它們的狀態更新順序就很重要,而Dispatcher哪管這些個兒女情長。因而開發者須要經過Dispatcher註冊回調函數返回的token來手動管理Store之間的依賴關係。
這無疑又是對開發者不友好的設計。
因此Redux乾脆,只維護一個全局的Store,讓你開發者再嗶嗶嗶。正事不幹,就知道嗶嗶嗶。
須要注意的是,Redux並無從機制上阻止開發者使用多個Store管理應用,開發者仍是能夠做妖的。不過這又回到Flux的老路上去了,對開發者一點好處都沒有。Redux選擇用思想和約定來約束開發者。
再來講函數式編程。
函數式編程思想的提出最先是爲了處理複雜的計算任務。計算任務的要求是什麼呢?結果可預期,任務之間不會相互影響。
相同的輸入,老是有相同的輸出。對應到函數,就是不能修改已有的數據,只要修改已有的數據,理論上就有可能輸出不一樣的結果。那麼我確實有修改數據的需求怎麼辦?生成一個新的衍生數據。
執行某個任務不會對外部產生影響,也就是所謂的沒有反作用。
咱們想一下,Redux加入函數式編程思想的目的不仍是爲了讓單項數據流更加清晰和單純麼?
Redux給前端帶來的另外一個重大成果是時間旅行式的調試。開發者能夠回到任意時間點的案發現場,看看那個臭蟲究竟是哪一個陰溝裏生出來的。
若是你看完本專題,就會發現Redux的做者Dan Abramov從一開始設計Redux就是奔着時間旅行式的調試去的。時間旅行纔是Redux寫法這麼繁瑣的罪魁禍首。
因此Flux的歷史功績是爲前端引入了一種思想,而Redux僅僅是改進這種思想而已,還算不上一代宗師。不過Redux原本就是Flux的門徒之一,做爲門徒可以將師門發揚光大也是一代豪傑了。
Redux專題一覽