Reflux學習心得

RefluxJS

一個簡單的單向數據流應用庫,靈感來自於ReactJS Flux.javascript

╔═════════╗       ╔════════╗       ╔═════════════════╗
║ Actions ║──────>║ Stores ║──────>║ View Components ║
╚═════════╝       ╚════════╝       ╚═════════════════╝
     ^                                      │
     └──────────────────────────────────────┘

同React Flux比較

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

npm install reflux

Bower

bower install reflux

使用

建立 actions

建立 一個 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'});

建立多個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');

參考

相關文章
相關標籤/搜索