数据流架构学习笔记(一)-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架构工作方式

你可能感兴趣的:(数据流架构学习笔记(一)-Flux)