前端技術 | 從MV*到Flux

最近要開始搞網頁端錢包,本着幹一行愛一行的原則,擼起了前端框架。前端

項目基於螞蟻金服的dva框架,其實是對幾個流行的開源框架的整合,技術棧包括:react

  • react
  • react-router
  • redux
  • redux-saga
  • dva
  • antd

在開始介紹以前,先說一說MV*。你們必定都據說過MVC,在這以後又衍生出了MVP和MVVM,這些均可以統稱爲MV*。可是,隨着前端代碼複雜度的增長,人們發現愈來愈難以管理程序的狀態,模塊之間耦合嚴重,代碼難以調試,所以不少人認爲「前端MVC已死」。編程

2014年,facebook提出了一個新的概念:Flux,旨在解決這些問題,其核心思想是「組件化 + 單向數據流」。這個框架很快流行了起來,而且逐漸成爲目前的主流前端框架之一。爲了更深入地理解這一變化,咱們來逐一比較一下它們之間的異同:redux

1.MVC

用戶首先經過View發起交互,View調用Controller執行業務邏輯,Controller修改Model,而後View經過觀察者模式檢測到Model的變化(具體表現形式能夠是Pub/Sub或者是觸發Events),刷新界面顯示。前端框架

從這裏能夠看出,主要業務邏輯都在Controller中,Controller會變得很重。MVC比較明顯的缺點:服務器

  • View依賴特定的Model,沒法組件化
  • View和Controller緊耦合,若是脫離Controller,View難以獨立應用(功能太少)

2.MVP

爲了克服MVC的上述缺點,MVP應運而生。在MVP中,View和Model是沒有直接聯繫的,全部操做都必須經過Presenter進行中轉。View向Presenter發起調用請求,Presenter修改Model,Model修改完成後通知Presenter,Presenter再調用View的相關接口刷新界面。這樣,View就不須要監聽具體Model的變化了,只須要提供接口給Presenter調用就能夠了。MVP具備如下優勢:antd

  • View能夠組件化,不須要了解業務邏輯,只需提供接口給Presenter
  • 便於測試:只須要給Presenter mock一個View,實現View的接口便可

3.MVVM

爲了進一步解放生產力,把Presenter中調用View的接口同步數據變化的重複工做抽象出來,作成一個binder模塊,這就變成了MVVM。開發者只須要指明綁定關係,binder模塊會自動完成數據同步,這就是所謂的「雙向數據流」,無論哪一端的數據發生變化,都會當即同步到另外一端。實際上,Vue.js、Angular這些流行的前端框架都使用了雙向數據流設計。react-router

雙向數據流極大地簡化了開發者的工做,可是詬病也隨之而來。因爲綁定的隨意性,某個View對Model進行的修改有可能會對其餘的View形成「連鎖反應」,再加上各類異步回調,給代碼調試形成了很大的困難,每每難以定位數據究竟是被誰修改掉的。用專業一點的術語來說,代碼的「可預測性」很是差。所以,爲了提升可預測性,不少人主張迴歸到「單向數據流」模式,其中的典型表明就是facebook的Flux框架。框架

4.Flux

其實Flux並非什麼新鮮事物,其背後仍是經典的MVC思想,可是實現方式上有所不一樣。Flux的核心是「組件化+單向數據流「,下面逐一進行介紹。異步

4.1組件化

在傳統的MVC設計中,Model中不只要存儲應用程序數據,還須要存儲UI狀態。另外一方面,Controller中不只要處理業務邏輯,還須要實現各類事件處理邏輯。若是把這部份內容抽出來,和View組合在一塊兒,就變成了「組件」。這樣一來,各個模塊均可以各司其職,專一於本身的領域,代碼的可讀性和複用性均可以獲得提升。

在實際編程中,通常把純界面展現的View實現成一個「無狀態組件」,在其上層再包裝一個Controller-View(也能夠稱爲Container),專門監聽事件並更新數據,而後把數據做爲props傳遞給View。這種編程模式能夠最大程度地提升組件的可複用性。

4.2單向數據流

爲了提升代碼的可預測性,Flux採用單向數據流設計。這裏引入了3個新概念:

  • Store:每一個程序能夠擁有多個Store,存儲應用程序狀態的不一樣部分。Store對View是隻讀的,只有Dispatcher能夠經過Store註冊的回調函數修改Store的內容
  • Action:當發生交互,須要修改Store內容時,須要發起一個Action,包含對應的type和payload
  • Dispatcher:當接收到Action時,會經過回調函數調用全部Store的,完成數據修改

當Store數據發生變化時,會發送一個事件,View或者Controller-View能夠監聽這個事件,而後完成界面刷新。整個過程是「單向」的,若是View想要繼續修改Store,必須從新發起一個Action。

固然,除了View之外,服務器或者Web API也能夠直接發送Action給Dispatcher,這就是爲何圖中Dispatcher有兩個輸入的緣由。

更爲詳細的Flux流程參見下圖:

經過以上分析能夠發現,所謂單向數據流並非什麼新鮮概念,實際上最最經典的MVC設計中,數據流就是單向的。雖然Flux官方宣稱它們不是MVC,但我我的認爲其實它實際想說的是MVVM,由於MVVM纔是雙向數據流。

固然,Flux也不是完美的,在多Store協同管理上存在必定的設計缺陷,這也是後來Redux出現的緣由,且聽下回分解。

最後,以一張思惟導圖結束本篇文章:

相關文章
相關標籤/搜索