zoukankan      html  css  js  c++  java
  • 【原】flux学习笔记

      最近React(web/native)依旧如火如荼,相信大家都跃跃欲试,入职新公司,现在的团队也开始在React领域有所尝试. 2016年应该是
    React 逐渐走向成熟的一年。之前在原来公司搞不懂的问题,同样是自学,发觉在新公司都搞懂了。哈哈,我也不知道为什么。

    flux是干嘛的?

    其实我刚开始学习的时候,一直不知道flux有什么鸟用。

    官方说法是:Flux是Facebook内部用来构建React应用的一套架构。它本身并不是一个框架或库。它仅仅是一个用于完善React应用开发的一种新的应用程序架构, Flux架构最大的特点是其倡导的是单向数据流方案。

      个人理解就是:比如我删除了一条数据,或者新增了一条数据,我怎么来让view知道我删除或者新增了该数据来做相应显示的改变呢,就是通过这种单向的数据流来告知,从而让数据的流动变得更加清晰。

    比如 action就专门来处理你是点击删除,还是新增件,dispatcher就专门来派发这些动作,store就专门用来对数据的删除,增加做操作。view就专门来更新视图和发出动作。我是这么理解的。

     

    首先来看看这张图:

    flux包括了四个东西:

    view: 视图

    action:动作

    dispatcher:派发器

    store:数据层

    打个比方,用户要删除一条数据,流程是这样的:  

     用户点击删除按钮-->传递给action,告诉action,我要删除啦-->派发器接收到了这个动作--->告诉store这个数据层。把用户点击的数据删除了-->store通过一个change时间告诉view,数据删掉了,然后显示的时候删掉的数据就没有了

    demo1

    写了一个demo,demo是在阮一峰大神的案例里做修改的。当然这篇文章也是基于阮一峰里的flux来写的,期间加一些自己的理解和思考

    阮一峰flux地址:http://www.ruanyifeng.com/blog/2016/01/flux.html#comment-text

    我的demo地址如下:https://github.com/xianyulaodi/myFluxTest

    界面是这样的:

    这个demo比较简单,就是数据的增加和删除,在输入框中输入内容,然后出来上面的东西,点击删除按钮可以对数据就行删除

    下面对demo进行解读:

    view部分

    index.jsx

    var React = require('react');
    var ReactDOM = require('react-dom');
    var MyButtonController = require('./components/MyButtonController');
    
    ReactDOM.render(
      <MyButtonController/>,
      document.querySelector('#example')
    );
    

    比较简单,就是将组建渲染到页面上

     component部分。

    这里面包含两个组件,一个是 MyButtonController.jsx, 一个MyButton.jsx

    MyButtonController.jsx内容如下:

    var React = require('react');
    // 引入数据层
    var ListStore = require('../stores/ListStore');
    // 引入动作层
    var ButtonActions = require('../actions/ButtonActions');
    var MyButton = require('./MyButton');
    
    var MyButtonController = React.createClass({
      
      getInitialState: function () {
        return {
          items: ListStore.getAll()
        };
      },
    
      componentDidMount: function() {
        ListStore.addChangeListener(this._onChange);
      },
    
      componentWillUnmount: function() {
        ListStore.removeChangeListener(this._onChange);
      },
    
      _onChange: function () {
        this.setState({
          items: ListStore.getAll()
        });
      },
    
      // view把用户的动作传给action。新增一个数据
      createNewItem: function (event) {
    
        var text=this.refs.myInput.value;
    
        if(text!==''){
          // 这个是action里面的函数 ,用户通过这个点击事件,告诉action,我点击了增加了按钮了
          ButtonActions.addNewItem(text);
    
          this.refs.myInput.value='';
    
        }else{
    
            alert('请输入内容');
        }
      },
    
      // 删除元素,告诉action,我点击了删除按钮
      deleteItem:function(id){
    
            ButtonActions.destroy(id);
      },
    
      render: function() {
        // 将事件传给这个组件的子组件,MyButton
         return (
                  <div>
                    <MyButton
                    items={this.state.items}
                    onClick={this.createNewItem}
                    delFn={this.deleteItem}
                    />
                    <input type="text" ref="myInput" placeholder="请输入内容" style={{"height":"25px","width":"200px","border":"1px solid #ccc"}}></input>
                  </div>
            )
         }
    
    });
    
    module.exports = MyButtonController;
    

     这里先介绍这个组件的两个函数,createNewItem 和deleteItem .这里就相当于view发出的action.当触发这个事件的时候,就调用action里面对应的事件,从而将用户的动作达到一个传给action的作用。

      MyButton是它的子组件,我们将这些事件传给它的子组件,由子组件来执行。

    MyButton.jsx的内容如下:

    var React = require('react');
    
    
    var MyButton = function(props) {
      var items = props.items;
      var _this=this;
      var itemHtml = items.map(function (ele, i) {
        return <li key={i}>您增加的文本是:{ele.text},它的id是 {ele.id}<a href="#" onClick={props.delFn.bind(_this,ele.id)} >点击删除</a></li>;
      });
    
      return <div>
                <ul>{itemHtml}</ul>
                <button onClick={props.onClick}>确认添加</button>
              </div>;
    };
    
    module.exports = MyButton;

    它的作用主要是显示我们的内容。比如新增了什么,点击是否删除等等。

    Action部分

    var AppDispatcher = require('../dispatcher/AppDispatcher');
    
    var ButtonActions = {
    
        // 从用户那里传来的动作
      addNewItem: function (text) {
        AppDispatcher.dispatch({
          actionType: 'ADD_NEW_ITEM',
          text: text
        });
      },
    
      destroy: function(id) {
        AppDispatcher.dispatch({
          actionType: 'DELETE_ITEM',
          id: id
        });
      },
    
    };
    
    module.exports = ButtonActions;

    因为我们只有两个动作,新增和删除,所以里面也只有两个事件。因为新增的是文本内容,所以我们传入text,因为删除是需要根据id来就行删除,所有我们传入id.

    Dispatcher部分

    var Dispatcher = require('flux').Dispatcher;
    var AppDispatcher = new Dispatcher();
    var ListStore = require('../stores/ListStore');
    
    // 用来接收action,并把它传递到store,一个页面有且只有一个dispatcher,而且是全局的
    AppDispatcher.register(function (action) {
      switch(action.actionType) {
        case 'ADD_NEW_ITEM':
          // 根据传入动作的不同,来调用不同的数据
          ListStore.addNewItemHandler(action.text);
          ListStore.emitChange();
          break;
          case 'DELETE_ITEM':
          ListStore.deleteItem(action.id);
          ListStore.emitChange();
          break;
        default:
          // no op
      }
    })
    
    module.exports = AppDispatcher;

      dispatcher的作用是派发器,根据不同的动作,来执行不同的store。也就是说,根据不同的动作,来生成不同的数据。比如上面的。如果你的动作是ADD_NEW_ITEM,那我就执行store里面的addNewItemHandler这个函数来生产数据。如果你是DELETE_ITEM这个动作,我就执行store里面的deleteItem这个动作来执行删除数据。

      dispatcher就是这样来联系action和store的。那我怎么告诉页面我删除或者新增数据了呢,store里面的emitChange帮我们完成了这个动作。每次数据的改变,就执行一下这个 emitChange.来告诉view,我新增数据啦,你给我赶紧跟着跟新,我删除数据啦,给老子跟新你的页面

      值得注意点是:在flux中,一个页面只有一个dispatcher.

    store部分

    // 这里就是相当于MVC中的model,只用来生成数据
    
    var EventEmitter = require('events').EventEmitter;
    var assign = require('object-assign');
    
    // Store 更新后(this.addNewItemHandler())发出事件(this.emitChange()),
    // 表明状态已经改变。 View 监听到这个事件,就可以查询新的状态,更新页面了。
    
    var ListStore = assign({}, EventEmitter.prototype, {
      items: [],
    
      getAll: function () {
        return this.items;
      },
    
      addNewItemHandler: function (text) {
        // 新增一个元素
        var id = (+new Date() + Math.floor(Math.random() * 999999)).toString(36);
        var obj= {
          id: id,
          text: text
        };
        this.items.push(obj);
      },
      
      deleteItem:function(id){
        // 删除指定元素
        var myItems=this.items;
        for (var i =0;i<myItems.length;i++) {
          var delId=myItems[i].id;
    
          if(id==delId){
              this.items.splice(i,1); 
          }
    
        }
        
      },
    
      emitChange: function () {
        this.emit('change');
      },
    
      addChangeListener: function(callback) {
        this.on('change', callback);
      },
    
      removeChangeListener: function(callback) {
        this.removeListener('change', callback);
      }
    });
    
    module.exports = ListStore;
    

      在flux中,store的作用是数据工厂,也就是说所有的数据操作都在这里执行,不管你是新增也好,删除也好。还有就是view里面的数据都是从这里来的。

    我们可以看到,我们首先定义了一个item这个数组用来存放数据。我们再来回看一下我们的 MyButtonController.jsx

    初始化状态也是直接拿我们store里面的数据。

    所以,flux就是一个数据流的操作方式,让我们的数据流动很清晰。向一条河流一样,流完这个地方才能到达另外一个地方。

    flux缺点:

      如果你搞懂了flux,虽然你会被他清晰的数据流所震撼和吸引,不过有没有发觉它很复杂,很啰嗦。比如我就想增加一个元素,兜了那么大的一个圈。

    这也是它不好的地方之一。而且如果一个项目中,有些人才会用,有些人不会用。那也不好沟通。

    所以在理解了flux之后,我准备去学redux了。

  • 相关阅读:
    Reading papers_2(与GMM相关,ing...)
    Matlab DIP(瓦)ch11表示与描述练习
    HMM学习笔记_1(从一个实例中学习DTW算法)
    Matlab DIP(瓦)ch10图像分割练习
    前景检测算法_2(帧差法1)
    目标跟踪学习笔记_3(particle filter初探2)
    基础学习笔记之opencv(2):haartraining前将统一图片尺寸方法
    Reading papers_5(与human activity analysis综述相关,ing...)
    总结系列_4(C++知识学习,续...)
    HMM学习笔记_2(从一个实例中学习HMM前向算法)
  • 原文地址:https://www.cnblogs.com/xianyulaodi/p/5358315.html
Copyright © 2011-2022 走看看