共计 3905 个字符,预计需要花费 10 分钟才能阅读完成。
Flux是Facebbook在React时发起的一种模式。特点就是严格的单向数据流。
Flux主要包含了3个部分:Dispatcher、Store、View
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,或者反之。
下面举例一下官方的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[重新渲染视图]
参考链接