數據流架構學習筆記(一)-Flux

由iOS原生開發轉到React Native開發,再接著慢慢開始學習前端開發,真心覺得搞技術太難了這句話太正確了。當前正在開發的項目中使用了Vue+Vuex+Electron來實現桌面應用開發,在學習了Vuex之后,決定對之前學的各種數據流管理架構做一個系統的總結,所以接下來我還會總結
數據流架構學習筆記(二)-Redux
數據流架構學習筆記(三)-Vuex
數據流架構學習筆記(一)-Flux 是這次系統總結的第一篇筆記,都是一些自己的學習和總結,權當學習參考。

Flux是什么?

Flux是Facebook官方提出一種架構思想,他的出現同樣也是為了解決實際項目中軟件結構的問題,如果你了解過MVC,MVVM之類的東西,其實就應該知道這是一樣的東西,他們是一種思想,為了讓你的應用能夠更加合理的工作和運行,具體到如何應用在你的項目中,通過代碼和一些工具可以仁者見仁、智者見智的使用。

Flux如何工作

一個 Flux 應用主要包含四個部分:

  • the dispatcher: 處理動作分發,并且向注冊的回調函數廣播payloads,維護 Store 之間的依賴關系
  • the stores: 應用程序狀態的容器,并且含有注冊到Dispatcher的回調函數,數據和邏輯部分
  • the views: 視圖組件,這一層可以看作controller-views,作為視圖同時響應用戶交互
  • the actions: 提供通過具體行為使用dispatcher 傳遞數據給 store,是一些使用Dispatcher傳遞數據的具體方法集合

Flux 的核心單向數據流是這樣運作的:

View -> Action -> Dispatcher -> Store -> View

更多時候 View 會通過用戶交互觸發 Action,所以一個簡單完整的數據流類似這樣:

假設現在在項目中,Action模塊、Stroe模塊、View模塊等都已建立成功,Dispatcher來自官方Flux庫,以從頁面登錄的例子進行一次Flux流程說明,流程如下:

  1. 頁面點擊登錄按鈕,View觸發點擊動作,調用Action中的網絡請求封裝函數;
  2. Action調用網絡庫相關API,并成功返回用戶登錄成功參數,或返回失敗錯誤。
  3. 在成功返回的callback中通過Dispatcher分發用戶信息Payload至Store更改數據并存儲新數據中。
  4. store通過前期已注冊的對應通知及emit()將最新的數據分發出去,頁面監聽到數據變化,從而更新頁面數據,重新渲染頁面。

實例應用

因為工作偏向React Native,這里以登錄流程中部分React Native代碼展示如何將Flux應用到React Native開發中進行數據管理,(由于代碼時間較久,存在一些不合理之處請忽略,但不影響Flux數據流的理解):

視圖層View:

登錄頁:

...
_login(userName, passWord) {
        LoginActions.login({
            username: userName,
            password: passWord,
            ...
        }, (response) => {
            this.props.navigator.resetTo({comp:MainContainer});
        }, (error) => {
            Alert.alert(
                '提示',
                'error',
                [{ text: '確定' }]
            );
        });
    }
...

主頁:

class  Main extends Component{
    constructor(props){
        super(props);
        this.state = {
            user: AppStore.getUser(),
            ...
        };
    }
    componentDidMount() {
       AppStore.addChangeListener(this._userStateChange, 'USER_CHANGE');
    }
    componentWillUnmount() {
       AppStore.removeChangeListener(this._userStateChange, 'USER_CHANGE');
    }
    _onChange: function () {
        this.setState({
            user: AppStore.getUser()
        });
    },
    ...
    ...
}

登錄頁是你的點擊交互事件,你通過點擊觸發登錄調用Action,主頁Main會存在登錄后返回的用戶信息,數據來源于你的數據倉庫AppStore,頁面當然還存在頁面監聽者,知道當你的數據改變的時候,知道該如何去更新你的頁面。

行為Action:

...
const _login = (params, callback, failure) => {
    const requestUrl = CommonLink.login(params.username, params.password);
   return Fetcher.getFetch(requestUrl)
       .then((response) => {
           AppDispatcher.dispatch({
               actionType: AppConstants.LOGIN,
               data: response.body,
           });
           callback(response);
       }).catch((error) => {
           failure(error);
       });
};
...
module.exports = {
    login: (params, callback, failure) => _login(params, callback, failure),
    ...
}

觸發一個行為調用Action方法進行了網絡API的調用,進行登錄,并返回成功用戶信息后,通過Dispatcher將數據和消息分發出去,把接下來的工作交給數據倉庫Store。

數據倉庫Stores:


const dataStore = {
    user: {},
    ...
}

const AppStore = _.assign({}, EventEmitter.prototype, EventEmitter.prototype._maxListeners = 30, {
  emitChange(event = 'DEFAULT_EVENT') {
    this.emit(event);
  },

  addChangeListener(callback, event = 'DEFAULT_EVENT') {
    this.on(event, callback);
  },

  removeChangeListener(callback, event = 'DEFAULT_EVENT') {
    this.removeListener(event, callback);
  },
  ...
  getUser: () => dataStore.user || {},
  ...
});

...

// Register callback to handle all updates
AppDispatcher.register((action) => {
  switch (action.actionType) {
    ...
    case AppConstants.LOGIN:
      _.assign(dataStore, {
        username: action.data.user.username,
        ...
      });
      AppStore.emitChange('USER_CHANGE');
      break;
    ...
  }
});

module.exports = AppStore;

在數據倉庫中,你應該定義出倉庫對象AppStore,并對AppDispatcher注冊入各種操作,即當接收到AppDispatcher發來的不同消息時,操作數據并保存數據到dataStore中,之后通過AppStore.emit()將更新通知發送到頁面中,讓頁面進行重新渲染。從而完成整個Flux數據流的閉環。

關于AppDispatcher和AppConstants

上述代碼中用到的AppDispatcher和AppConstants代碼如下:
AppDispatcher:

import {Dispatcher} from 'flux'
module.exports = new Dispatcher();

AppConstants:

const keyMirror = require('keymirror');

const AppConstants = keyMirror({
  ...
  LOGIN: null,
  ...
});
module.exports = AppConstants;

可以看出這些只是為了更好的使用Flux而引入庫和輔助工具,你也可以使用其他類似工具。

總結

Flux學習和理解需要的是在項目中實際應用進去,同樣只要理解了單向數據流的思想,理解Flux也是很快的,Flux是單向數據流的一種具體架構實現。接下來會再總結關于Redux的理解和使用,同樣也是單向數據流的一種具體實現,基于Flux,但是比Flux更加方便和強大。而當前的很多React開發項目也都基于使用Redux。

雖然搞技術很難,但是做自己喜歡的事情還是很開心的,一起學習,努力奮斗。

參考博客:

Flux 架構入門教程-阮一峰
詳解React Flux架構工作方式

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,353評論 25 708
  • 原教程內容詳見精益 React 學習指南,這只是我在學習過程中的一些閱讀筆記,個人覺得該教程講解深入淺出,比目前大...
    leonaxiong閱讀 2,860評論 1 18
  • 人的一生如果沒有年齡這個概念,我們對自己狀態的把握可能會變得更有效率,比如,我并不知道自己已經五十歲,在我的概念里...
    心甲閱讀 245評論 1 0
  • 這只小鳥,林子里凡是見過它的,都說它沒有煩惱,大家一提到它就臉上泛笑,全說終于相信了世界上真的存在無憂無慮。這...
    湯米湯伯虎閱讀 545評論 0 0
  • “生活不僅是眼前的茍且,還有詩和遠方?!庇谑牵S多人像打了雞血一樣的充滿亢奮。其實我以為,生活除了眼前的茍且,剩下...
    獨彝無二閱讀 2,041評論 4 4