react开发中,组建直接传递参数或者事件都需要props一层层代理,对于复杂组件,它可能嵌套的子组件非常多,层级也比较深,那么,如果还采用props链条来维护组件通信或者数据共享,将非常困难,也不利于开发和维护。因此,顺序地衍生出了Flux、Redux和react-redux,本篇主要介绍Flux。
Flux框架也是一种MVC框架,它采用单向数据流,不允许Model和Control互相引用。Flux框架大致如下:
Views:视图界面
Action:驱动Dispatcher来触发状态变化
Dispatcher:负责分发,关联Action(接收方)与Store(处理方)
Store:状态变化的逻辑处理、状态存储
Flux Demo演示代码:https://github.com/smallH/react-flux-demo.git
通过该Demo大家可以了解到Flux的运行机制,那么直接看代码吧,视图界面 :
// FluxDemo.jsx
import React from 'react';
import FluxView from './FluxView.jsx';
import FluxStore from './FluxStore.js';
class FluxDemo extends React.Component {
constructor(props) {
super(props);
this.state = {
data: FluxStore.getData()
};
this.onChange = this.onChange.bind(this);
}
componentDidMount() {
FluxStore.addChangeListener(this.onChange);
}
componentWillUnmount() {
FluxStore.removeChangeListener(this.onChange);
}
onChange() {
const newData = FluxStore.getData();
this.setState({
data: newData
});
}
render() {
return(
<div>
<FluxView data={this.state.data}/>
</div>
);
}
}
export default FluxDemo;
重点:(1)挂载完成和卸载时,要添加/移除store中监听;(2)传递到子组件的状态必须从store中获得。这样子组件中触发Action后,经过一系列过程最终驱动store里的状态变化,意味着传递的状态也跟着变化。
FluxView 组件,该组件主要模拟了通过点击按钮触发Action操作:
// FluxView.jsx
import React from 'react';
import FluxAcion from './FluxAcion';
class FluxView extends React.Component {
constructor(props) {
super(props);
this.state = {};
this.newHandle = this.newHandle.bind(this);
this.updateHandle = this.updateHandle.bind(this);
}
newHandle() {
FluxAcion.newData("[new action]");
}
updateHandle() {
FluxAcion.updateData("[update action]");
}
render() {
return(
<div>
current data is ======= {this.props.data}
<div>
<button onClick={this.newHandle}>execute action [New] </button>
<button onClick={this.updateHandle}>execute action [Update] </button>
<button>...</button>
</div>
</div>
);
}
}
export default FluxView;
Dispatcher、Action 代码如下:
// FluxDispatcher.js
import { Dispatcher } from 'flux';
const FluxDispatcher = new Dispatcher();
export default FluxDispatcher;
// FluxConstants.js
const FluxContants = {
NEW: 'NEW',
UPDATE: 'UPDATE'
};
export default FluxContants;
// FluxAcion.js
import FluxConstants from './FluxConstants';
import FluxDispatcher from './FluxDispatcher';
const FluxAcion = {
newData(data) {
// Dispatcher 触发
FluxDispatcher.dispatch({
type: FluxConstants.NEW,
value: data
});
},
updateData(data) {
// Dispatcher 触发
FluxDispatcher.dispatch({
type: FluxConstants.UPDATE,
value: data
});
}
}
export default FluxAcion;
Action的作用就是驱动Dispatcher,从而分发任务,这时若store只有注册了Dispatcher监听,就会收到来自Action的任务。
最后,看看Flux最核心的store:
// FluxStore.js
import { EventEmitter } from 'events';
import FluxDispatcher from './FluxDispatcher';
import FluxConstants from './FluxConstants';
let data = "[default]";
// store 构造
const store = Object.assign({}, EventEmitter.prototype, {
getData: function() {
return data;
},
emitChange: function() {
this.emit('change');
},
addChangeListener: function(callback) {
this.on('change', callback);
},
removeChangeListener: function(callback) {
this.removeListener('change', callback);
}
});
// Dispatcher 注册
FluxDispatcher.register((action) => {
switch(action.type) {
case FluxConstants.NEW:
data = action.value + "+ 数据操作所需的逻辑处理...";
store.emitChange();
break;
case FluxConstants.UPDATE:
data = action.value + "+ 数据操作所需的逻辑处理...";
store.emitChange();
break;
default:
break
}
});
export default store;
store实现了从Dispatcher处得到数据来源和类型,然后对数据的进行逻辑处理,并向外提供了一个getData()的接口,让组件可以获取变化后的状态数据,最终形成一个闭环,这个模式就是Flux。
通过点击按钮去驱动[New] Action 和 [update] Action 实现当前data状态的变化。
Flux有两个缺点:
1. 一个应用可以拥有多个store、action,多个store直接可能有依赖关系。
2. Store封装了数据和处理数据的逻辑。
3. 使用Flux的组件复用性差,具有Flux元素耦合,不符合react设计思想。