React(10)-Flux简介

Flux是Facebbook在React时发起的一种模式。特点就是严格的单向数据流。

Flux主要包含了3个部分:Dispatcher、Store、View
flux
Dispatcher:可以理解为整个应用的控制中心,Stroe:数据中心,View:视图(React View)。

前面两个webapi的可以理解为后端数据,从ActionCreators开始。
当ActionCreators的状态或者属性发生变化时(一般是后端传递数据WebApi或者用户输入UserInteractions),会触发一个Actions,这个Actions会传递给Dispatcher,Dispatcher拿到这个数据之后,通过先前注册好的回调函数,去找对应的Stroe方法来处理这个Action。每创建一个Stroe就会向Dispatcher注册,并有一个回调函数Callback,告诉它,我这有一个新的Stroe,你有需要的时候就来找我。Stroe拿到数据就是增删改查了,完毕之后,Stroe会广播一个事件(Change Event +  Stroe Queries)到React View,如果有组件关心这个事件,就会去向这个Stroe要数据了。这样就触发了熟悉的React的属性或者状态发生改变,需要更新组件了。对于复杂的应用,流程会复杂一些。不一定是一个萝卜一个坑,可能是一个Stroe对应两个View,或者反之。

flux-fu
下面举例一下官方的TODO实例

首先看App.js,这里面其实很简单,关键的是

var TodoApp = require('./components/TodoApp.react');

接着查看TodoApp.react.js

var Footer = require('./Footer.react');
var Header = require('./Header.react');
var MainSection = require('./MainSection.react');
//前三个是编写好的组件
var React = require('react');
var TodoStore = require('../stores/TodoStore');

function getTodoState() {
 return {
   //获取数据
   allTodos: TodoStore.getAll(),
   areAllComplete: TodoStore.areAllComplete()
 };
}
var TodoApp = React.createClass({
 getInitialState: function() {
    return getTodoState();
 },
 componentDidMount: function() {
   //添加改变事件
   TodoStore.addChangeListener(this._onChange);
 },
 componentWillUnmount: function() {
   TodoStore.removeChangeListener(this._onChange);
 },
 render: function() {
   return (
    <div>
       <Header />
       <MainSection
            allTodos={this.state.allTodos}
            areAllComplete={this.state.areAllComplete}
        />
       <Footer allTodos={this.state.allTodos} />
    </div>
   );
 },
 _onChange: function() {
   this.setState(getTodoState());
 }
});
module.exports = TodoApp;

关键是看TodoStore,那个看这个JS都做了什么。

//需要的Dispatcher
var AppDispatcher = require('../dispatcher/AppDispatcher');
//事件添加器,第三方
var EventEmitter = require('events').EventEmitter;
//常量
var TodoConstants = require('../constants/TodoConstants');
//第三方库
var assign = require('object-assign');

//事件名字
var CHANGE_EVENT = 'change';

var _todos = {};
function create(text) {
 var id = (+new Date() + Math.floor(Math.random() * 999999)).toString(36);
 _todos[id] = {
 id: id,
 complete: false,
 text: text
 };
}
function update(id, updates) {
 _todos[id] = assign({}, _todos[id], updates);
}
...

//前面的几个函数就是要做什么事情
//这个是整个JS返回的对象
var TodoStore = assign({}, EventEmitter.prototype, {
 //是否发生改变
 areAllComplete: function() {
    for (var id in _todos) {
      if (!_todos[id].complete) {
        return false;
      }
    } 
    return true;
 },
 //返回所有数据
 getAll: function() {
    return _todos;
 },
 //发出一个广播事件
 emitChange: function() {
   this.emit(CHANGE_EVENT);
 },
 //添加监听
 addChangeListener: function(callback) {
    this.on(CHANGE_EVENT, callback);
 },
 //移除监听
 removeChangeListener: function(callback) {
    this.removeListener(CHANGE_EVENT, callback);
 }
});

// 把回调函数注册到Dispatcher上
AppDispatcher.register(function(action) {
 var text;
 //action.actionType操作的类型
 switch(action.actionType) {

 case TodoConstants.TODO_CREATE:
    text = action.text.trim();
    if (text !== '') {
     create(text);
     //发出一个事件谁用谁拿
     TodoStore.emitChange();
   }
 break;
 case TodoConstants.TODO_TOGGLE_COMPLETE_ALL:
    if (TodoStore.areAllComplete()) {
      updateAll({complete: false});
    } else {
      updateAll({complete: true});
    }
    TodoStore.emitChange();
 break;
 .
 .
 .
 default:
 // no op
 }
});

module.exports = TodoStore;

接着看Dispatcher,其实它就是引用了一个Dispatcher,做的事情就是循环所有stroe。看看谁关心action。

最后看TodoActions.js

var AppDispatcher = require('../dispatcher/AppDispatcher');
var TodoConstants = require('../constants/TodoConstants');
var TodoActions = {
 create: function(text) {
    //dispatch 真正的做一件事
    //对于所有操作的一个抽象
    AppDispatcher.dispatch({
     actionType: TodoConstants.TODO_CREATE,
     text: text
    });
 },
 ...
};
module.exports = TodoActions;

Flux数据流:是单向数据流

Flux各个部分

  • Action,从用户上看,每一个行为都会创建一个被发送到Dispatcher的Action。它是一个对象,上面有很多对应的事件的一个抽象操作。
  • Dispatcher:它是所有用户交互和数据流的中心仓库有。在Flux模式中它是一个单例。它负责在Stroe上注册回调函数以及管理它们之间的依赖,用户的Action会流入Dispatcher,数据会传递到注册过的Action的Stroe当中。
  • Stroe负责封装应用的业务逻辑与应用数据交互。Stroe通过注册Action来选择响应那些Action。Stroe把内部数据通过更改时的Change事件发送到React的组件当中。Stroe包含应用的所有数据;Stroe是唯一改变数据的地方;Stroe没有赋值,所有的更改都是有Dispatcher发送到Stroe的。
  • View,当组件被加载时添加Change事件监听,当Stroe发生改变时,组件按照需要重新请求数据并完成相应的操作,当组件被卸载时,清除事件监听。
  • 注册依赖行为。Dispatcher.register(function(action){...});

总结:

React View == [发起] -> Action==[调度] -> Dispatcher ==[执行回调] -> Stroe ==[触发Change事件] -> React View[重新渲染视图]

参考链接