Flux是Facebook用来构建客户端Web应用的应用架构。它利用单向数据流
的方式来组合React中的视图组件。它更像一个模式而不是一个正式的框架,开发者不需要太多的新代码就可以快速的上手Flux。
工作流程
1、用户访问 View
2、View 发出用户的 Action
3、Dispatcher 收到 Action,要求 Store 进行相应的更新
4、Store 更新后,发出一个"change"事件
5、View 收到"change"事件后,更新页面
四个组成部分
View:
视图层
Action(动作):
视图层发出的消息(比如click) 调用 dispatch方法发数据
Dispatcher
(派发器):用来接收Actions、执行回调函数-register 方法接收
Store(数据层)
:用来存放应用的状态,一旦发生变动,就提醒Views要更新页面
dispatcher与action
dispatcher是事件调度中心,flux模型的中心枢纽,管理着Flux应用中的所有数据流。它本质上是Store的回调注册。每个Store注册它自己并提供一个回调函数。当Dispatcher响应Action时,通过已注册的回调函数,将Action提供的数据负载发送给应用中的所有Store。应用层级单例
Store
Store负责封装应用的业务逻辑跟数据的交互。
Store中包含应用所有的数据
Store是应用中唯一的数据发生变更的地方
Store中没有赋值接口—所有数据变更都是由dispatcher发送到store,新的数据随着Store触发的change事件传回view。Store对外只暴露getter,不允许提供setter!!禁止在任何地方直接操作Store。
controller-view
controller-view 可以理解成MVC模型中的controller,它一般由应用的顶层容器充当,负责从store中获取数据并将数据传递到子组件中。简单的应用一般只有一个controller-view,复杂应用中也可以有多个。controller-view是应用中唯一可以操作state的地方(setState())
view
view(UI组件) ui-component 职责单一只允许调用action触发事件,数据从由上层容器通过属性传递过来。
actionCreator
actionCreators是相对独立的,它作为语法上的辅助函数以action的形式使得dispatcher传递数据更为便利。
flux核心api
Action为对象方法 接收view的响应
方法内部响应dispatcher对象的dispatch方法
Dispatch对象 由 flux对象引入Dispatcher对象 创建 Dispatch对象 new Dispatcher()
响应action的dispatch 方法 在dispatch对象中使用 register注册回调接收数据
Dispatch.register((action)=>{}) action参数为Action对象方法提供的数据
判断符合条件 调用store的相应处理方法以及change事件
Store中change事件的触发通过this.emit 监听改变通过 this.on() 使用的是events模块中EventEmitter对象
拷贝属性方法使用 object-assign 原生js依赖中的 assign对象
顶层容器中调用store的获取数据 以及在dom加载完成函数中调用store监听
步骤
创建一个react脚手架
创建一个文件夹fls,小技巧创建五个组成部分,5个文件,Actions.js、Demo.js、Dispatch.js、Store.js、TodoController.js
Store 添加 发送, 监听 获取所有数据
Action.js
//active----动作层
var Action ={
addTodos(text){
return{
actionType:"ADD_TODO",
text:text
}
},
rmTodos(text){
return{
actionType:'RM_TODO',
text:text
}
}
}
export default Action;
Demo.js
//view---用来进行数据展示
import React from "react";
class Demo extends React.Component{
add(){
this.props.name(this.refs.ipt.value)
this.refs.ipt.value="" //点击add把输入框里面的值传给顶层容器,并清空输入框
}
del(i){
this.props.remove(i) //点击删除删除这一个
}
render(){
var _this = this;
return(
<div>
<h1>TodeList</h1>
<input type="tezt" ref="ipt"/>
<button onClick={_this.add.bind(this)}>点击</button>
{
this.props.list.map(function(item,i){
return(
<div key={i}>{item}---<button onClick={_this.del.bind(_this,i)}>删除</button></div>
)
})
}
</div>
)
}
}
export default Demo;
Dispatch.js
//派发器---事件调度中心----接受action 命令store修改
import {Dispatcher} from "flux";
import Store from "./Store";
//实例化派发器对象
var Dispatch = new Dispatcher()
Dispatch.register((action)=>{
//判断一下action的类型
switch (action.actionType) {
case "ADD_TODO":
//命令store添加数据---action.text---store-change
Store.addtodoitem(action.text) //添加数据
Store.changes() //发出change事件
break;
case "RM_TODO":
Store.removeTodoItem(action.text)
Store.changes()
break;
}
})
export default Dispatch;
Store.js
//仓库--发出change事件
//Store==存储数据,执行修改数据的业务逻辑,发出change(emit)
import {EventEmitter} from "events";
//拷贝对象
import assign from "object-assign";
var Store=assign({},EventEmitter.prototype,{
Todos:[], //存储所有的数据
addtodoitem(text){ //添加数据
this.Todos.push(text)
},
removeTodoItem(text){
this.Todos.splice(text,1)
},
changes(){//修改成功后发出change事件,类似于监听
this.emit("change")
},
changelisten(callback){
this.on('change',callback)
},
getAll(){
return this.Todos //讲store里面的所有数据通过这个函数返回过来
}
})
export default Store
TodoController.js
import React from "react";
import Demo from "./Demo"
import Action from "./Action";
import Dispatch from './Dispatch';
import Store from './Store';
class TodoController extends React.Component{
constructor(props){
super(props)
this.state={
list:Store.getAll()
}
this.changeitem = this.changeitem.bind(this)
}
addTodo(text){
// text==视图容器里面的数据
Dispatch.dispatch(Action.addTodos(text)) //派发器通过dispatch方法来接受actions里面的add方法
}
removeTodo(i){
Dispatch.dispatch(Action.rmTodos(i))
}
changeitem(){ //调用setState的方法
this.setState({list:Store.getAll()})
}
componentDidMount(){
Store.changelisten(this.changeitem)
}
render(){
return(
<div>
<h1>顶层容器</h1>
<Demo name={this.addTodo} list={this.state.list} remove={this.removeTodo}/>
</div>
)
}
}
export default TodoController;