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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,588评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,456评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,146评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,387评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,481评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,510评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,522评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,296评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,745评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,039评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,202评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,901评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,538评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,165评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,415评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,081评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,085评论 2 352

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,973评论 25 707
  • 原教程内容详见精益 React 学习指南,这只是我在学习过程中的一些阅读笔记,个人觉得该教程讲解深入浅出,比目前大...
    leonaxiong阅读 2,822评论 1 18
  • 人的一生如果没有年龄这个概念,我们对自己状态的把握可能会变得更有效率,比如,我并不知道自己已经五十岁,在我的概念里...
    心甲阅读 230评论 1 0
  • 这只小鸟,林子里凡是见过它的,都说它没有烦恼,大家一提到它就脸上泛笑,全说终于相信了世界上真的存在无忧无虑。这...
    汤米汤伯虎阅读 514评论 0 0
  • “生活不仅是眼前的苟且,还有诗和远方。”于是,许多人像打了鸡血一样的充满亢奋。其实我以为,生活除了眼前的苟且,剩下...
    独彝无二阅读 2,024评论 4 4