一个简单的单向数据流应用库,灵感来自于ReactJS Flux.javascript
╔═════════╗ ╔════════╗ ╔═════════════════╗ ║ Actions ║──────>║ Stores ║──────>║ View Components ║ ╚═════════╝ ╚════════╝ ╚═════════════════╝ ^ │ └──────────────────────────────────────┘
refluxjs的目标是为了让咱们更容易的搭建Web应用程序。
做者的blog post about React Flux vs Reflux.java
有actionsreact
有storesjquery
单向数据流git
经过内部拓展actions的行为,移除了单例的dispatchergithub
stores能够监听actions的行为,无需进行冗杂的switch判断npm
stores能够相互监听,能够进行进一步的数据聚合操做,相似于,map/reducejson
waitFor被连续和平行的数据流所替代segmentfault
npm install reflux
bower install reflux
建立 一个 actions 是用 Reflux.createAction
须要传递一个参数,这个参数是一个object.app
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'});
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'})
异步操做(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();
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
当须要给全部的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');
建立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'});
给说有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');
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 } });
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! } });
在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'));
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 将自动在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,有数据跟新将自动调用this.setState()方法
var Status = React.createClass({ mixins: [Reflux.connect(statusStore,"currentStatus")], render: function() { // render using `this.state.currentStatus` } });
对数据加了一层过滤器。
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` } });
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');