一個簡單的單向數據流應用庫,靈感來自於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');