RefluxJS
一个简单的单向数据流应用库,灵感来自于ReactJS Flux.
╔═════════╗ ╔════════╗ ╔═════════════════╗
║ Actions ║──────>║ Stores ║──────>║ View Components ║
╚═════════╝ ╚════════╝ ╚═════════════════╝
^ │
└──────────────────────────────────────┘
同React Flux比较
refluxjs的目标是为了让我们更容易的搭建Web应用程序。
作者的blog post about React Flux vs Reflux.
相同点
有actions
有stores
单向数据流
不同点
通过内部拓展actions的行为,移除了单例的dispatcher
stores可以监听actions的行为,无需进行冗杂的switch判断
stores可以相互监听,可以进行进一步的数据聚合操作,类似于,map/reduce
waitFor被连续和平行的数据流所替代
安装
NPM
npm install reflux
Bower
bower install reflux
使用
创建 actions
创建 一个 actions 是用 Reflux.createAction
需要传递一个参数,这个参数是一个object.
var TodoAction = Reflux.createAction(options);
调用action statusUpdate
TodoAction(data);
TodoAction.triggerAsync(data); // or 效果相同的
返回值是一个函数,调用这个函数就会触发相应的事件,在store中监听这个函数,并作相应的处理
var TodoAction = Reflux.createAction();
var TodoStore = Reflux.createStore({
init: function () {
this.listenTo(addItem, 'todo');
},
todo: function (model) {
console.log(model);
}
});
TodoAction({name: 'xxx'});
创建多个Action
var TodoActions = Reflux.createActions([
'addItem',
'deleteItem'
]);
var TodoStore = Reflux.createStore({
init: function () {
this.listenTo(TodoActions.addItem, 'addItem');
this.listenTo(TodoActions.deleteItem, 'deleteItem');
},
addItem: function (model) {
console.log(model)
},
deleteItem:function(model){
console.log(model);
}
});
TodoActions.addItem({name:'xxx'});
// console.log({name:'xxx'})
TodoActions.deleteItem({name:'yyy'});
// console.log({name:'yyy'})
异步 actions
异步操作(e.g. API calls),在最典型的情况下,我们考虑完成和失败的操作。
要创建这些数据流相关的actions,我们可以使用options.asyncResult
.设置为true
import Reflux from 'reflux';
import $ from 'jquery';
let UserActions = Reflux.createActions({
init: {asyncResult: true}
});
UserActions.init.listen( function() {
$.getJSON('/data/user.json')
.then( this.completed, this.failed )
});
let UserStore = Reflux.createStore({
listenables: UserActions,
onInitCompleted: function (data) {
console.log(data)
this.trigger(data)
},
onInitFailed: function (err) {
console.log(err)
}
});
UserActions.init();
Action hooks
Reflux为每个action都提供了两个hook方法
preEmit(params),action emit之前调用,用于修改action传递过来的参数 返回值会传递给shouldEmit
shouldEmit(params) action emit之前调用,参数默认是action传递,如果preEmit有返回值,则是preEmit返回值,返回值必须为真,才决定emit
使用案例:
var TodoAction = Reflux.createAction({
preEmit: function (params) {
console.log('preEmit:' + params);
},
shouldEmit: function (params) {
console.log('shouldEmit:' + params);
}
});
var TodoStore = Reflux.createStore({
init: function () {
this.listenTo(TodoAction, 'todo');
},
todo: function (params) {
console.log('todo:' + params);
}
});
addItem('xxx');
控制台打印
$ preEmit:xxx
$ shouldEmit:xxx
当然也可以写在action 内部
var TodoAction = Reflux.createAction({
preEmit: function (params) {
console.log('preEmit:' + params);
return 324;
},
shouldEmit: function (params) {
console.log('shouldEmit:' + params);
return true;
}
});
var TodoStore = Reflux.createStore({
init: function () {
this.listenTo(TodoAction, 'todo');
},
todo: function (params) {
console.log('todo:' + params);
}
});
TodoAction('xxx');
控制台打印
$ preEmit:xxx
$ shouldEmit:324
$ todo:324
Reflux.ActionMethods
当需要给所有的action添加公用方法时,可以使用: Reflux.ActionMethods
。
使用案例:
Reflux.ActionMethods.print = function (str) {
console.log(str);
};
var TodoAction = Reflux.createAction();
var TodoStore = Reflux.createStore({
init: function () {
this.listenTo(TodoAction, 'todo');
},
todo: function (params) {
console.log('todo:' + params);
}
});
TodoAction.print('xxx');
Stores
创建store
创建store跟 ReactJS 的React.createClass
方法相似,我们用Reflux.createStore
在init函数中监听actions
// Creates a DataStore
var TodoActions = Reflux.createActions([
'addItem',
'deleteItem'
]);
var TodoStore = Reflux.createStore({
init: function () {
this.listenTo(TodoActions.addItem, 'addItem');
this.listenTo(TodoActions.deleteItem, 'deleteItem');
},
addItem: function (model) {
console.log(model);
},
deleteItem: function (model) {
console.log(model);
}
});
TodoActions.addItem({name: 'xxx'});
TodoActions.deleteItem({name: 'yyy'});
Reflux.StoreMethods
给说有store添加公共方法
Reflux.StoreMethods.print = function (str) {
console.log(str);
};
var TodoAction = Reflux.createAction();
var TodoStore = Reflux.createStore({
init: function () {
this.listenTo(TodoAction, 'dodo');
},
todo: function (model) {
console.log(model);
}
});
TodoStore.print('rrr');
Mixins in stores
store 中的mixins 是跟React components一样的.
var MyMixin = { mixinMethod: function() { console.log(this.foo); } }
var Store = Reflux.createStore({
mixins: [MyMixin],
foo: 'bar!',
storeMethod: function() {
this.mixinMethod(); // outputs "bar!" to console
}
});
一次监听多个anction
listenToMany 方法
处理方法只需让action的标识首字母大写并加上on就可以了。
标识如果首字母大写就会识别不了,例如将上面的fireBall改成FireBall就识别不了。
var actions = Reflux.createActions(["fireBall","magicMissile"]);
var Store = Reflux.createStore({
init: function() {
this.listenToMany(actions);
},
onFireBall: function(){
// whoooosh!
},
onMagicMissile: function(){
// bzzzzapp!
}
});
对listenToMany 进一步简化 设置listenables 参数
var actions = Reflux.createActions(["fireBall","magicMissile"]);
var Store = Reflux.createStore({
listenables: actions,
onFireBall: function(){
// whoooosh!
},
onMagicMissile: function(){
// bzzzzapp!
}
});
Component
基本
在componentDidMount 监听store中的数据变化,在componentWillUnmount中取消监听
var TodoComponent = React.createClass({
getInitialState: function () {
return {list: []};
},
onStatusChange: function (list) {
this.setState({list: list});
},
componentDidMount: function () {
this.unsubscribe = TodoStore.listen(this.onStatusChange);
TodoActions.getAll();
},
componentWillUnmount: function () {
this.unsubscribe();
},
render: function () {
return (
<div>
{this.state.list.map(function (item) {
return <p>{item}</p>
})}
</div>
)
}
});
React.render(<TodoComponent />, document.getElementById('container'));
结合 React 的 mixin 使用
var Status = React.createClass({
mixins: [Reflux.ListenerMixin],
onStatusChange: function(status) {
this.setState({
currentStatus: status
});
},
componentDidMount: function() {
this.listenTo(statusStore, this.onStatusChange);
},
render: function() {
// render specifics
}
});
使用 Reflux.listenTo
使用 Reflux.listenTo 将自动在componentDidMount绑定监听函数
var Status = React.createClass({
mixins: [Reflux.listenTo(statusStore,"onStatusChange")],
onStatusChange: function(status) {
this.setState({
currentStatus: status
});
},
render: function() {
// render using `this.state.currentStatus`
}
});
当然还有 Reflux.listenToMany 函数,使用相同的方法监听
使用 Reflux.connect
当我们想要更新组件的状态,使用Reflux.connect,有数据跟新将自动调用this.setState()方法
var Status = React.createClass({
mixins: [Reflux.connect(statusStore,"currentStatus")],
render: function() {
// render using `this.state.currentStatus`
}
});
使用 Reflux.connectFilter
对数据加了一层过滤器。
var PostView = React.createClass({
mixins: [Reflux.connectFilter(postStore, "post", function(posts) {
return posts.filter(function(post) {
return post.id === this.props.id;
}.bind(this))[0];
})],
render: function() {
// render using `this.state.post`
}
});
监听其他stores中数据的改变 (聚合 data stores)
var TodoActions = Reflux.createActions([
'addItem'
]);
var TodoStore = Reflux.createStore({
items: [],
listenables: [TodoActions],
onAddItem: function (model) {
this.items.push(model);
this.trigger(this.items);
}
});
var statusHistoryStore = Reflux.createStore({
init: function() {
this.listenTo(TodoStore, this.output);
this.history = [];
},
output: function(statusString) {
this.history.push({
date: new Date(),
status: statusString
});
// Pass the data on to listeners
this.trigger(this.history);
console.log(this.history)
}
});
TodoActions.addItem('xxx');
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。