2

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');

参考


狂奔滴小马
28 声望0 粉丝

狂奔滴小马


下一篇 »
redux快速上手

引用和评论

0 条评论