阿西河

所有教程

公众号
🌙
阿西河前端的公众号

我的收藏

    最近访问  (文章)

      教程列表

      抓包专区
      测试专区

      Reflux 学习笔记

      Reflux

      受ReactJS Flux启发的单向数据流体系结构的简单库。

      官方资料

      RefluxJS

      一个简单的单向数据流应用库,灵感来自于ReactJS Flux.

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

      同React Flux比较

      refluxjs的目标是为了让我们更容易的搭建Web应用程序。

      相同点

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

      参考

      目录
      目录