本文根据 Devhints / Flux architecture 翻译。代码示例及版本范围沿用原文。
关于
关于
Flux 是一种用于构建客户端 Web 应用程序的架构。
- 深入概览 (facebook.github.io)
架构
-
Dispatcher 分发器 接收 动作 (actions) 并将它们分发给各自的监听器。
-
Store 存储 是用于存储数据的对象,通常由调度器的监听器来修改。
-
视图 (Views) 是 React 组件,它们监听 Store 的变化,或向 动作 (actions) 调度器发送(动作)。
Dispatcher 分发器
发布-订阅 (Pub-sub)
分发器 向其监听者 (listeners) 发送事件 (.dispatch()).register(fn)).
var Dispatcher = require('flux').Dispatcher;
d = new Dispatcher();
// send
d.dispatch({ action: 'edit', ... };
// receive
token = d.register(function (payload) {
payload.action === 'edit'
})
确保正确的执行顺序
当有多个监听者时,你可以通过以下方式确保它们按特定顺序依次触发: .waitFor().
token1 = d.register(...);
token2 = d.register(function (payload) {
// ensure receiver 1 is fired before this
d.waitFor([ token1 ]);
// process here
})
通过子类化 (Subclassing)
Object.assign 这是扩展 Dispatcher 的首选方式(可以参考 $.extend).
你还可以创建 动作创建器 (action creators),它们本质上是……的快捷方式 dispatch().
var Dispatcher = require('flux').Dispatcher;
var assign = require('object-assign');
var AppDispatcher = assign({}, Dispatcher.prototype, {
// action creator
handleViewAction(action) {
this.dispatch({
source: 'VIEW_ACTION',
action: action
})
}
})
Store 存储
普通对象 (Plain objects)
Store 本质上就是对象。
var TodoStore = { list: [] };
事件
有时它们也充当事件发射器(event emitter)。通常,它们被用来发射 change 事件,供视图(view)捕获。
var TodoStore = assign({}, EventEmitter.prototype, {
...
});
TodoStore.emit('change');
TodoStore.on('change', function () { ... });
模型逻辑
逻辑有时可以归于存储(store)中。
{
isAllActive() {
return this.list.every(item => item.active);
}
}
存储与分发器(dispatcher)
实例化
创建分发器和存储。
d = new Dispatcher();
TabStore = { tab: 'home' };
更新数据
通过分发事件来修改存储。
d.dispatch({ action: 'tab.change', tab: 'timeline' });
d.register(function (data) {
if (data.action === 'tab.change') {
TabStore.tab = data.tab;
}
});
结合视图
监听分发器
视图(React 组件)可以监听 Dispatcher。
var TodoApp = React.createClass({
componentDidMount() {
this.token = AppDispatcher.register((payload) => {
switch (payload.action) {
case 'tab.change':
this.render();
// ...
}
});
},
componentDidUnmount() {
AppDispatcher.unregister(this.token);
}
});
监听存储
或者监听存储所发出的 change 事件。
{
componentDidMount() {
TodoStore.on('change', this.onChange);
},
componentDidUnmount() {
TodoState.removeListener('change', this.onChange);
},
onChange(data) {
// ...
}
}