我對 React Flux 架構的理解

React Flux架構簡介

我的現階段對Flux架構的理解,求拍磚求star!
原文連接:https://github.com/kuitos/kuitos.github.io/issues/27前端

React 簡介請戳 這裏react

Flux是什麼

Flux是Facebook用來構建客戶端web應用的應用架構。它利用單向數據流的方式來組合react中的視圖組件。它更像一個模式而不是一個正式的框架,開發者不須要太多的新代碼就能夠快速的上手Flux。git

Flux的核心部分

1. dispatcher

事件調度中心,flux模型的中心樞紐,管理着Flux應用中的全部數據流。它本質上是Store的回調註冊。每一個Store註冊它本身並提供一個回調函數。當Dispatcher響應Action時,經過已註冊的回調函數,將Action提供的數據負載發送給應用中的全部Store。應用層級單例!!github

2. store

負責封裝應用的業務邏輯跟數據的交互。web

  • Store中包含應用全部的數據redux

  • Store是應用中惟一的數據發生變動的地方架構

  • Store中沒有賦值接口---全部數據變動都是由dispatcher發送到store,新的數據隨着Store觸發的change事件傳回view。Store對外只暴露getter,不容許提供setter!!禁止在任何地方直接操做Store。框架

3. view

  • controller-view 能夠理解成MVC模型中的controller,它通常由應用的頂層容器充當,負責從store中獲取數據並將數據傳遞到子組件中。簡單的應用通常只有一個controller-view,複雜應用中也能夠有多個。controller-view是應用中惟一能夠操做state的地方(setState())異步

  • view(UI組件) ui-component 職責單一隻容許調用action觸發事件,數據從由上層容器經過屬性傳遞過來。mvvm

4. 其餘

action creators 做爲dispatcher的輔助函數,一般能夠認爲是Flux中的第四部分。ActionCreators是相對獨立的,它做爲語法上的輔助函數以action的形式使得dispatcher傳遞數據更爲便利。

How Flux(Unidirectional Data Flow) Works

  1. view --> actionCreators

    // Nav.jsx
    export default class Nav extends React.Component {
    
      _handleClick(nav) {
        NavActionCreators.clickNav(nav);
      }
    
      render() {
    
        let itemList = this.props.list.map((nav, index) => {
          return (
            <li className="index-menu-item" onClick={this._handleClick.bind(this, nav)} key={index}>
              <span>{nav.text}</span>
            </li>
          );
        });
    
        return (
          <nav className="index-menu">
            <ul className="index-menu-list">
              {itemList}
            </ul>
          </nav>
        );
      }
    }
  2. action dispatch

    // NavActionCreators.js
    export default {
    
      clickNav(nav){
    
        AppDispatcher.dispatch(
          {
            type: ActionTypes.CLICK_NAV,
            nav
          }
        );
      }
    };
  3. dispatcher --> store callback

    AppDispatcher.register(action => {
    
      switch (action.type) {
    
        // nav點擊
        case ActionTypes.CLICK_NAV:
    
          IndexWebAPIUtils.getGiftList(_currentUserInfo.userId, action.nav.id)
            .then(function (giftList) {
    
              _currentGiftList = giftList;
              IndexStore.emitChange();
            });
    
          break;
    
        // no default
      }
    });
  4. store emitChange --> controller view --> setState

    export default class Index extends React.Component {
    
      constructor(props) {
        super(props);
        let currentUser = UserStore.getCurrentUser();
        this.state = IndexStore.getAll();
      }
    
      componentDidMount() {
        IndexStore.addChangeListener(this._onChange.bind(this));
      }
    
      componentWillUnmount() {
        IndexStore.removeChangeListener(this._onChange.bind(this))
      }
    
      _onChange() {
        this.setState(IndexStore.getAll());
      }
    
      render() {
    
        let state = this.state;
    
        return (
          <div className="page active">
            ...
            <Nav list={state.navList}/>
            ...
          </div>
        );
      }
    
    }

Flux vs MVVM

MVVM

1. 簡單的MVVM

2. 複雜的MVC

Flux

1. 複雜的Flux

Flux的優點

1. 數據狀態變得穩定同時行爲可預測

由於angular雙向綁定的緣由,咱們永遠沒法知道數據在哪一刻處於穩定狀態,因此咱們常常會在angular中看到經過setTimeout的方式處理一些問題(其實有更優雅的解決方案,不在本次討論以內)。同時因爲雙向綁定的緣由,行爲的流向咱們也很難預測,當視圖的model變多的時候,若是再加上一堆子視圖依賴這些model,問題發生時定位簡直是噩夢啊(這也是angular的錯誤信息那麼不友好的緣由,由於框架開發者也沒法肯定當前行爲是誰觸發的啊,綁定的人太多了...)。可是這裏仍是要強調一點就是,並非說雙向綁定就必定會致使不穩定的數據狀態,在angular中咱們經過一些手段依然可使得數據變得穩定,只是雙向綁定(mvvm)相對於flux更容易引起數據不穩定的問題。

2. 全部的數據變動都發生在store裏

flux裏view是不容許直接修改store的,view能作的只是觸發action,而後action經過dispatcher調度最後纔會流到store。全部數據的更改都發生在store組件內部,store對外只提供get接口,set行爲都發生在內部。store裏包含全部相關的數據及業務邏輯。全部store相關數據處理邏輯都集中在一塊兒,避免業務邏輯分散下降維護成本。

3. 數據的渲染是自上而下的

view全部的數據來源只應該是從屬性中傳遞過來的,view的全部表現由上層控制視圖(controller-view)的狀態決定。咱們能夠把controller-view理解爲容器組件,這個容器組件中包含若干細小的子組件,容器組件不一樣的狀態對應不一樣的數據,子組件不能有本身的狀態。也就是,數據由store傳遞到controller-view中以後,controller-view經過setState將數據經過屬性的方式自上而下傳遞給各個子view。

4. view層變得很薄,真正的組件化

因爲二、3兩條緣由,view自身須要作的事情就變得不多了。業務邏輯被store作了,狀態變動被controller-view作了,view本身須要作的只是根據交互觸發不一樣的action,僅此而已。這樣帶來的好處就是,整個view層變得很薄很純粹,徹底的只關注ui層的交互,各個view組件以前徹底是鬆耦合的,大大提升了view組件的複用性。

5. dispatcher是單例的

對單個應用而言dispatcher是單例的,最主要的是dispatcher是數據的分發中心,全部的數據都須要流經dispatcher,dispatcher管理不一樣action於store之間的關係。由於全部數據都必須在dispatcher這裏留下一筆,基於此咱們能夠作不少有趣的事情,各類debug工具、動做回滾、日誌記錄甚至權限攔截之類的都是能夠的。

Flux的困境

1. 過多的樣板代碼

flux只是一個架構模式,並非一個已實現好的框架,因此基於這個模式咱們須要寫不少樣板代碼,代碼量duang的一會兒上來了。。不過好在目前已經有不少好用的基於flux的第三方實現,目前最火的屬redux。

2. dispatcher是單例

dispatcher做爲flux中的事件分發中心,同時還要管理全部store中的事件。當應用中事件一多起來事件時序的管理變得複雜難以維護,沒有一個統一的地方能清晰的表達出dispatcher管理了哪些store。

3. 異步處理到底寫在哪裏

  • 按flux流程,action中處理:依賴該action的組件被迫耦合進業務邏輯

  • 按store職責在store中處理:store狀態變得不穩定,dispatcher的waitFor失效

4. 至今尚未官方實現

寫在最後

  • 前端摩爾定律:前端每18個月難度增長一倍

  • 沒有銀彈

相關文章
相關標籤/搜索