【11】react 之 flux

Flux 是 Facebook 使用的一套前端应用的架构模式。React 标榜自己是 MVC 里面 V 的部分,那么 Flux 就相当于添加 M 和 C 的部分。

1.1.  Flux介绍

Flux并不是一项新的技术,而是一种架构模式,一个Flux应用由四个部分:

View: 视图层(组件)

Action(动作):视图层发出的消息(比如mouseClick)

{
    type:’save’,
   payload:’明天不能休息,自己在家把react弄一弄’
}

Dispatcher(派发器):用来接收Actions、执行回调函数

if(action.type==’save’){

//执行保存代码。。。。。

store.add(xxxx);

store.emit(‘change’);

}

Store(数据层):用来存放应用的状态(数据),一旦发生变动,就提醒Views要更新页面

 

Flux 的最大特点:以单向数据流方式支持MVC,Flux执行流程:

1、一个Action由系统或View 层通过用户交互触发;

2、Dispatcher 会分发触发的 Action 给所有注册的 Store 的回调函数;

3、Store 回调函数根据接收的 Action 更新自身数据之后会触发一个 change 事件通知 View 数据更改了;

4、View 会监听这个 change 事件,拿到对应的新数据并调用 setState 更新组件 UI;

Action -> Dispatcher -> Store -> View

View->Action -> Dispatcher -> Store -> View

1.2.  Flux安装

npm i flux -save

1.3.  Flux View

Flux中的View其实就是React中的组件,与我们以前编写的组件没有任何区别。

index.js 入门文件

import React from 'react';
import ReactDOM from 'react-dom';
import TodoApp from './flux/TodoApp';

ReactDOM.render(
	<TodoApp />,
	document.getElementById('app')
);

TodoApp 主应用组件

import React from 'react';
import TextInput from './TextInput';
import TodoList from './TodoList';
class TodoApp extends React.Component{
	constructor(){
		super();
		this.state = {
			datas : [12,123,123]
		};
	}
	render(){
		return (
			<div>
				<TextInput />
				<TodoList datas={this.state.datas} />
			</div>
		);
	}
	
}
export default TodoApp;

  

TextInput.js 备忘录输入框组件

import React from 'react';
// 备忘录,用户输入内容,按下回车键保存数据
class TextInput extends React.Component{
    constructor(){
        super();
        this.state ={value:""};
    }
    //键盘按下回车键
    _onKeyDown(event){
        //判断是否是回车键
        if(event.keyCode == 13){
            //保存到本地

            //清空输入框
            this.setState({
                value:""
            });
        }
    }

    _onChange(event){
        this.setState({
            value:event.target.value
        });
    }
    render(){
        return (
            <div>
                <input type="text" name="username" onChange={this._onChange.bind(this)} onKeyDown={this._onKeyDown.bind(this)} value={this.state.value}/>
            </div>
        );
    }
}
export default TextInput;

TodoList.js 备忘录列表

import React from 'react';
class TodoList extends React.Component{
	constructor(){
		super();
	}
	render(){
		var datas = this.props.datas;
		var lis = datas.map(function(data,index){
			return <li key={index}>{data}</li>;
		});
		return (
			<ul>
				{lis}
			</ul>
		);
	}
}

export default TodoList;

1.4.  Flux Dispatcher

一个应用只需要一个 dispatcher 作为分发中心,管理所有数据流向,分发action给 Store,没有太多其他的逻辑(一些 action creator 方法也可以放到这里)。Facebook官方的 Dispatcher 实现输出一个类,你要写一个AppDispatcher.js,生成 Dispatcher 实例。

//AppDispatcher.js
//Dispatcher分发器,管理所有数据流向,分发动作给 Store。
var Dispatcher = require('flux').Dispatcher;
export default new Dispatcher();

1.5.  Flux Action

Action:应用中的一个动作,比如“添加”,“删除”...

首先要创建动作,通过定义一些 action creator(动作创建者)方法来创建,这些方法用来暴露给外部调用,通过 dispatch 分发对应的动作,所以 action creator 也称作 dispatcher helper methods 辅助 dipatcher 分发.

TodoActions.js

import React from 'react';
import AppDispatcher from './AppDispatcherAppDispatcher';

var TodoActions = {
	todoAddItem:function(text){
		
		//创建action动作,然后通过AppDispatcher分发到store进行数据处理
		AppDispatcher.dispatch({
			actionType : 'todo_addItem',
			text : text
		});
		
	},
	destroy:function(){
		AppDispatcher.dispatch({
			actionType : 'todo_removItem'
		});

	}
};
export default TodoActions;

 有了action creator(动作创造者)我们就可以View中触发这些动作。

TextInput.js

 _onKeyDown(event){
        //判断是否是回车键
        if(event.keyCode == 13){
            //保存到本地(调用action)
            TodoAction.todoAddItem(this.state.value);
            //清空输入框
            this.setState({
                value:""
            });
        }
    }

1.6.  Flux Store

Flux四个部分,已经完成了三个,但是现在还没有地方处理我们的数据。

View:视图,数据交互(输入、输出),触发动作。

Dispatcher:分发器,把动作发送给响应的Store处理。

Action:动作,描述动作的类型和动作的数据。

Store:管理整个应用的状态数据(对数据进行实际操作)。

mport {EventEmitter} from 'events';
//由于 Store 需要在变动后向 View 发送"change"事件,因此它必须实现事件接口。
//Object.assign 对象拷贝。 多个源对象(第二参数开始对象)的拷贝给目标对象(第一个参数对象)
var TodoStore = Object.assign({},EventEmitter.prototype,{
  items: [],
  getData: function() {
    return this.items;
  },
  addItem: function (text) {
    this.items.push(text);
  },
  emitChange: function () {
    this.emit('change');
  },
  addChangeListener: function(callback) {
    this.on('change', callback);
  },
  removeChangeListener: function(callback) {
    this.removeListener('change', callback);
  }
});

export default TodoStore;
//ListStore.items用来保存条目,ListStore.getAll()用来读取所有条目,ListStore.emitChange()用来发出一个"change"事件。

最后一步:注册到 dispatcher,通过动作类型过滤处理当前 Store 关联的动作

import AppDispatcher from './AppDispatcher';
//最后一步:注册到 dispatcher,通过动作类型过滤处理当前 Store 关联的动作
AppDispatcher.register(function(action){
	switch(action.actionType){
		case 'todo_addItem':
			TodoStore.addItem(action.text);//调用Store方法进行数据操作
			TodoStore.emitChange();//触发修改事件,通知view更新状态
		break;
	}
});

1.7.  Flux完结

import React from 'react';
import TextInput from './TextInput';
import TodoList from './TodoList';
import TodoStore from './TodoStore'
class TodoApp extends React.Component{
         constructor(){
           super();
           this.state = {
                datas : TodoStore.getData()
          };
         }
         _onChange(){
           his.setState({datas : TodoStore.getData()});
         }
         componentDidMount(){
                   TodoStore.addChangeListener(this._onChange.bind(this));
         }
         componentWillUnmount(){
                   TodoStore.removeChangeListener(this._onChange.bind(this));
         }
         render(){
                   return (
                            <div>
                  <TextInput />
                     <TodoList datas={this.state.datas} />
                 </div>

                   );

         }

}

export default TodoApp;

  

 

posted on 2017-08-13 14:41  yezixuan  阅读(345)  评论(0编辑  收藏  举报