react之flux小结

来源:互联网 发布:ssH访问境外服务器端口 编辑:程序博客网 时间:2024/05/16 16:05

react之flux小结

flux是facebook开源的一个单向数据流的框架。

flux架构应用一般由以下几部分组成:

  1. store 存储应用的状态数据
  2. dispatcher 负责动作的分发和处理,维护store的数据
  3. action 触发dispatcher的动作分发,并传递数据
  4. view 视图,作为与用户交互的入口 如react组件

    首先创建Action,这些action会暴露给外部,作为改变state的入口,用于响应用户的操作或某些其它web事件,如响应服务端消息等

import TodoActionTypes from './TodoActionTypes';import TodoDispatcher from './TodoDispatcher';const Actions = {  addTodo(text) {    TodoDispatcher.dispatch({      type: TodoActionTypes.ADD_TODO,      text,    });  },  completeTodo() {    TodoDispatcher.dispatch({      type: TodoActionTypes.COMPLETE_TODO,      id,    });  },

Action被触发后,只是表达了想要修改的意图,把数据和具体的type类型通过dispatcher分发下去了,那么具体如何处理呢?需要在dispatcher中注册了
TodoStore.js

var CHANG_EVENT="change";var _todos=[]function docreate(id){    var id=Counter.increcement();//+1    _todos[id]={        id:id,        text:text;        done:false;    }}function docomplete(id){    if(_todos[id]){        _todos[id].done=true;    }}var TodoStore={    getAll:funciton{        return _todos    }}TodoDispatcher.register(function(action){    var value;    switch(action.actionType){        case TodoActionTypes.ADD_TODO:        value=action.text;             if(value !== ''){                docreate(value);            }            break;        case TodoActionTypes.COMPLETE_TODO:        value=action.id;             if(value !== ''){                docomplete(value);            }            break;    }})

其中docreate和dodelete方法是内部改变store的数据的方法,而store对外暴露的数据接口只有getAll方法(也即外部无法直接改变store数据,只能通过触发action方法,由action调用dispatch方法进而进入曾对dispatcher注册过的回调函数的处理流程,到这里则回到了store的内部方法,也即注册回调函数时时在store内注册的)

现在看上去,好像store 的数据已经更新了,但这对我们来说还不够,因为现在store 的变化对我们的view层没有任何影响,而我们的最终目的是要让视图产生变化才行,否则没有任何意义,所以下面对部分代码做一些修改

让TodoStore继承EventEmitter,可以触发并监听事件,如下

var TodoStore=assign({},EventEmitter.prototype,{    getAll:funciton{        return _todos    }    emitChange: function(){        this.emit(CHANG_EVENT);    }    addChangeListner:funciton(callback){        this.on(CHANGE_EVENT,callback)    }    removeChangeListener:function(callback){        this.removeListener(CHANGE_EVENT,callback);    }})

其中新添加了emitChange方法和addChangeListner,removeChangeListener方法,从名字也可以略知一二,这几个方法分别用来绑定监听事件和触发事件,无疑为store的数据的改变和外部监听到这一状态提供了一个钩子,其中emitChange只需在dispatcher的每个处理流程中state改变以后调用即可,而addChangelistner是有一个callback函数作为参数的,只需在view层组件中把想要在状态改变后触发的函数作为参数传入这个函数即可,这样,view层组件就可以完美的监控到store中数据的变化(一旦监控到变化,又可以调用store的getAll方法,即在这个回调函数中调用,即可和store中改变后的数据衔接),并做出相应的改变了。
更改后的代码如下:
注册dispatcher的部分

TodoDispatcher.register(function(action){    var value;    switch(action.actionType){        case TodoActionTypes.ADD_TODO:        value=action.text;             if(value !== ''){                docreate(value);            }            TodoStore.emitChange();            break;        case TodoActionTypes.COMPLETE_TODO:        value=action.id;             if(value !== ''){                docomplete(value);            }            TodoStore.emitChange();            break;    }})

最后来看一下View的state是如何和Store的数据绑定的,这里的view用的react组件

var React =require('react');var TodoStore= require('../TodoStore')function getTodoState(){    return {        allTodos: TodoStore.getAll();    }}var TodoApp = React.createClass({    getInitialState: funciton(){        return getTodoState();    }    componentDidMount: funciton(){        TodoStore.addChangeListner(this._onChange);    }    componentWillUnmont: funciton(){        TodoStore.removeChangeListener(this._onChange);    }    _onChange:function(){        this.setState(getTodoState())    }    render:function(){        return .....    }})

现在flux的思路已经梳理完了,可以发现,flux的确带给我们一个新世界,自上而下的单项数据流,使各部分分工都很明确,高度的解耦合,但是也是又它的弊端的,比如说在一个大型程序中会有多个的store,而这些每个组件和各个store的关系需要开发人员时时刻刻的维护,比如在componentDidMount中绑定监听事件,来监听store的某个事件(状态改变事件)在事件中将组件的状态赋值为特定的store的相关状态,进而触发组件本身的更新,在dispatcher注册的回调函数中每个流程中改变state后都必须调用函数,来触发一个状态改变的事件,这一系列看上去很固定的流程,是不是有进一步的解决办法呢?

原创粉丝点击