React Reflux
概念Reflux是根据React的flux创建的单向数据流类库。 ╔═════════╗ ╔════════╗ ╔═════════════════╗ ║ Actions ║──────>║ Stores ║──────>║ View Components ║ ╚═════════╝ ╚════════╝ ╚═════════════════╝ ^ │ └──────────────────────────────────────┘ 代码看起来像这样的: var TodoActions = Reflux.createActions([ 'addItem' ]); var TodoStore = Reflux.createStore({ items: [1,2],listenables: [TodoActions],onAddItem: function (model) { $.post('/server/add',{data: model},function (data) { this.items.unshift(data); this.trigger(this.items); }); } }); var TodoComponent = React.createClass({ mixins: [Reflux.listenTo(TodoStore,'onStatusChange')],getInitialState: function () { return {list: []}; },onStatusChange: function () { this.setState({list: TodoStore.items}); },render: function () { return ( <div> {this.state.list.map(function (item) { return <p>{item}</p> })} </div> ) } }); React.render(<TodoComponent />,document.getElementById('container')); 同React Flux比较相同点
不同点
创建Actionvar statusUpdate = Reflux.createAction(options); 返回值是一个函数,调用这个函数就会触发相应的事件,在store中监听这个函数,并作相应的处理 var addItem = Reflux.createAction(); var TodoStore = Reflux.createStore({ init: function () { this.listenTo(addItem,'addItem'); },addItem: function (model) { console.log(model); } }); addItem({name: 'xxx'}); 创建多个Actionvar TodoActions = Reflux.createActions([ 'addItem','deleteItem' ]); store监听actions的行为: 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'}); 异步Action真实的应用场景中,几乎所有的操作都会向后端请求,而这些操作都是异步的,Reflux也提供了相应的Promise接口 var getAll = Reflux.createAction({asyncResult:true}); 例如获取全部数据: var getAll = Reflux.createAction({asyncResult: true}); var TodoStore = Reflux.createStore({ init: function () { this.listenTo(getAll,'getAll'); },getAll: function (model) { $.get('/all',function (data) { if (data) { getAll.completed(data); } else { getAll.failed(data); } }); } }); getAll({name: 'xxx'}) .then(function (data) { console.log(data); }) .catch(function (err) { throw err; }); Action hooksReflux为每个action都提供了两个hook方法
情景一: var addItem = Reflux.createAction({ preEmit: function (params) { console.log('preEmit:' + params); },shouldEmit: function (params) { console.log('shouldEmit:' + params); } }); var TodoStore = Reflux.createStore({ init: function () { this.listenTo(addItem,addItem: function (params) { console.log('addItem:' + params); } }); addItem('xxx'); 控制台打印 $ preEmit:xxx $ shouldEmit:xxx 情景二: var addItem = 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(addItem,addItem: function (params) { console.log('addItem:' + params); } }); addItem('xxx'); 控制台打印 $ preEmit:xxx $ shouldEmit:324 $ addItem:324
Action Methods当需要给所有的action添加公用方法时,可以这么干: Reflux.ActionMethods.print = function (str) { console.log(str); }; var addItem = Reflux.createAction(); var TodoStore = Reflux.createStore({ init: function () { this.listenTo(addItem,addItem: function (params) { console.log('addItem:' + params); } }); addItem.print('xxx'); trigger、triggerAsync和triggerPromise直接调用addItem()实际上是调用trigger或者triggerAsync或者triggerPromise,它们区别在于 var addItem = Reflux.createAction(); addItem(); #默认调用triggerAsync,相当于addItem.triggerAsync() var addItem = Reflux.createAction({sync:true});addItem(); #默认调用trigger,相当于addItem.trigger() var addItem = Reflux.createAction({asyncResult:true});addItem();#默认调用triggerPromise,相当于addItem.triggerPromise() trigger和triggerAsync区别在于: triggerAsync = setTimeout(function () { trigger() },0); trigger和triggerPromise区别在于,triggerPromise的返回值是promise 创建StoreStore可以响应Action的行为,并同服务器交互。 监听单个Action在init方法中添加监听处理 var addItem = Reflux.createAction(); var TodoStore = Reflux.createStore({ init: function () { this.listenTo(addItem,addItem: function (model) { console.log(model); } }); addItem({name: 'xxx'}); 监听多个Action作死写法var TodoActions = Reflux.createActions([ 'addItem',addItem: function (model) { console.log(model); },deleteItem: function (model) { console.log(model); } }); TodoActions.addItem({name: 'xxx'}); TodoActions.deleteItem({name: 'yyy'}); 两个action的时候在init里写了两遍监听处理方法,如果有十个甚至多个的话,写起来就像这样的: var TodoActions = Reflux.createActions([ 'item1','item2','item3','item4','item5','item6','item7','item8','item9','item10' ]); var TodoStore = Reflux.createStore({ init: function () { this.listenTo(TodoActions.item1,'item1'); this.listenTo(TodoActions.item2,'item2'); this.listenTo(TodoActions.item3,'item3'); this.listenTo(TodoActions.item4,'item4'); this.listenTo(TodoActions.item5,'item5'); this.listenTo(TodoActions.item6,'item6'); this.listenTo(TodoActions.item7,'item7'); this.listenTo(TodoActions.item8,'item8'); this.listenTo(TodoActions.item9,'item9'); this.listenTo(TodoActions.item10,'item10'); },item1: function (model) { console.log(model); },item2: function (model) { console.log(model); } }); TodoActions.item1({name: 'xxx'}); TodoActions.item2({name: 'yyy'}); listenToMany还好Reflux给我们提供了listenToMany方法,避免重复劳动: var TodoActions = Reflux.createActions([ 'item1','item10' ]); var TodoStore = Reflux.createStore({ init: function () { this.listenToMany(TodoActions); },onItem1: function (model) { console.log(model); },onItem2: function (model) { console.log(model); } }); TodoActions.item1({name: 'xxx'}); TodoActions.item2({name: 'yyy'}); 处理方法只需让action的标识首字母大写并加上on就可以了。
listenablesvar TodoActions = Reflux.createActions([ 'item1','item10' ]); var TodoStore = Reflux.createStore({ listenables: [TodoActions],onItem2: function (model) { console.log(model); } }); TodoActions.item1({name: 'xxx'}); TodoActions.item2({name: 'yyy'}); 一般我们写真实应用的时候都应该采用这种写法!!! Store Methods拓展Store的公用方法有两种方式。 方式一Reflux.StoreMethods.print = function (str) { console.log(str); }; var addItem = Reflux.createAction(); var TodoStore = Reflux.createStore({ init: function () { this.listenTo(addItem,addItem: function (model) { console.log(model); } }); TodoStore.print('rrr'); 方式二var Mixins = { print: function (str) { console.log(str); } } var addItem = Reflux.createAction(); var TodoStore = Reflux.createStore({ mixins: [Mixins],init: function () { this.listenTo(addItem,addItem: function (model) { console.log(model); } }); TodoStore.print('rrr'); 同组件结合前面说了,Action、Store和组件这三者是通过事件机制响应变化的,构建组件的时候首先需要监听Store的状态。 var TodoActions = Reflux.createActions([ 'getAll' ]); var TodoStore = Reflux.createStore({ items: [1,2,3],onGetAll: function () { this.trigger(this.items); } }); 基本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')); 这里有两点需要注意:
Mixinsvar TodoComponent = React.createClass({ mixins: [Reflux.ListenerMixin],render: function () { return ( <div> {this.state.list.map(function (item) { return <p>{item}</p> })} </div> ) } }); React.render(<TodoComponent />,document.getElementById('container')); Reflux.listenTovar TodoComponent = React.createClass({ mixins: [Reflux.listenTo(TodoStore,componentDidMount: function () { TodoActions.getAll(); },document.getElementById('container')); Reflux.connectvar TodoComponent = React.createClass({ mixins: [Reflux.connect(TodoStore,'list')],document.getElementById('container')); 数据会自动更新到state的list当中。 Reflux.connectFiltervar TodoComponent = React.createClass({ mixins: [Reflux.connectFilter(TodoStore,'list',function (list) { return list.filter(function (item) { return item > 1; }); })],document.getElementById('container')); 对数据加了一层过滤器。
小结我这人喜欢拿代码来表述思想。 var TodoActions = Reflux.createActions([ 'getAll','addItem','deleteItem','updateItem' ]); var TodoStore = Reflux.createStore({ items: [1,onGetAll: function () { $.get('/all',function (data) { this.items = data; this.trigger(this.items); }.bind(this)); },onAddItem: function (model) { $.post('/add',model,function (data) { this.items.unshift(data); this.trigger(this.items); }.bind(this)); },onDeleteItem: function (model,index) { $.post('/delete',function (data) { this.items.splice(index,1); this.trigger(this.items); }.bind(this)); },onUpdateItem: function (model,index) { $.post('/update',function (data) { this.items[index] = data; this.trigger(this.items); }.bind(this)); } }); var TodoComponent = React.createClass({ mixins: [Reflux.connect(TodoStore,render: function () { return ( <div> {this.state.list.map(function(item){ return <TodoItem data={item}/> })} </div> ) } }); var TodoItem = React.createClass({ componentDidMount: function () { TodoActions.getAll(); },handleAdd: function (model) { TodoActions.addItem(model); },handleDelete: function (model,index) { TodoActions.deleteItem(model,index); },handleUpdate: function (model) { TodoActions.updateItem(model); },render: function () { var item=this.props.data; return ( <div> <p>{item.name}</p> <p>{item.email}</p> <p>/*操作按钮*/</p> </div> ) } }); React.render(<TodoComponent />,document.getElementById('container')); 实际情况远比这复杂,只是提供一个思路供大家参考。 代码链接github 参考Reflux (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |