react (五)Flux小结(内含MVC小知识)
来源:互联网 发布:wampserver无法打开php 编辑:程序博客网 时间:2024/06/06 03:53
从MVC到Flux
一、 MVC框架
把应用分为三个部分:
- Model(模型):负责管理数据
- View(视图):负责渲染用户界面
- Controller(控制器):赋值接受用户输入,根据用户输入调用对应的Model部分逻辑,把产生的数据结果交给View部分呢,让View渲染出必要的输出。
缺点:无法禁绝View和Model之间的直接对话。
二、Flux框架
优点:
通过设置规则,即如果要改变界面,必须改变Store中的状态,如果要改变Store中的状态,必须派发一个action对象,规则禁绝了数据流混乱的可能。
Flux与MVC的对应关系:(左:flux,右:MVC)
view =》 view
dispatcher =》 controller
store =》 model
action =》 请求
缺点:
1、Store之间依赖关系。
当两个Store之间有逻辑依赖关系,就必须用上Dispatcher的waitFor函数。
另外,每一个Store是通过register函数的返回值dispatchToken标志的。
某些Store必须要等待其他Store处理完action后,才能进行操作。
2、难以进行服务器渲染
facebook设计flux时,就不是用作服务器端渲染的。
3、Store混杂了逻辑和状态。
做不到动态替换一个Store的逻辑。但是Redux可以做到。
三、Flux框架实例应用(修改前面的案例为flux框架应用)
首先,需要使用npm安装一下flux,此处不赘述了。
- 第一步:创建Dispathcer类,作用:用于派发action。
实例化一个dispatcher实例,进行action分发操作、store注册操作等。
import {Dispatcher} from 'flux';export default new Dispatcher();
- 第二步:action配置,通常包括两小步:
- 首先,定义ActionTypes.js文件,用于定义对象的多种类型type,通常为字符串。
- 其次,定义Actions.js文件,用于定义action的多个构造函数,在构造函数内部,会通过dispatcher实例对象提供的dispatch函数派发出去。
【注意:此文件中,每一个构造函数并不是action对象本身,而是能够产生并派发action对象的函数。】
/*ActionTypes.js文件内容*/export const INCREMENT ='increment';export const DECREMENT ='decrement';
/*Actions.js文件内容*//*当文件有多个使用export导出时,可以用此语法将所有导出融为一个对象进行访问。*/import * as ActionTypes from './ActionTypes.js';import AppDispatcher from './AppDispatcher.js';export const increment =(counterCaption)=>{ AppDispatcher.dispatch({ type:ActionTypes.INCREMENT, counterCaption:counterCaption });};export const decrement=(counterCaption)=>{ AppDispatcher.dispatch({ type:ActionTypes.DECREMENT, counterCaption:counterCaption });};
- 第三步:定义不同组件的不同store对象,用于存储应用状态,同时还要接受Dispatcher派发的动作,根据动作来决定是否要更新应用状态。
Tips:由于store会有多个,所以单独建立了一个stores文件夹进行存储为好。
注意:虽然名为store,但并不表示一个Store必须要存储,Store只是提供获取数据的方法,二Store提供的数据完全可以另一个Store计算得来。
/*CounterStore.js文件内容 */import AppDispatcher from '../AppDispatcher';import * as ActionTypes from '../ActionTypes';const counterValues={ 'First':0, 'Second':10, 'Third':30};// 1、使用消息的方式建立Store和View的联系,相当于CounterStore成了EventEmitter实例对象。支持了emit、on、removeListener函数。const CounterStore=Object.assign({},EventEmitter.prototype,{ getCounterValues:function(){ return counterValues; }, emitChange:function(){ this.emit(CHANGE_EVENT); }, addChangeListener:function(callback){ this.on(CHANGE_EVENT,callback); }, removeChangeListener:function(callback){ this.removeListener(CHANGE_EVENT,callback); }});// 2、store只有注册到Dispatcher实例上才能真正发挥作用// 3、回调函数 作用:根据action对象来决定如何更新自己的状态// 其中的形参action:是派发给dispatcher的action对象(第三步中的操作)CounterStore.dispatchToken=AppDispatcher.register((action)=>{ if(action.type===ActionTypes.INCREMENT){ counterValues[action.counterCaption]++; CounterStore.emitChange(); }else if(action.type===ActionTypes.DECREMENT){ counterValues[action.counterCaption]--; CounterStore.emitChange(); }});export default CounterStore;
展示总和的组件Summary单独建立自己的store文件,SummaryStore.js。
import AppDispatcher from '../AppDispatcher';import * as ActionTypes from '../ActionTypes';import CounterStore from './CounterStore';function computeSummary(counterValues){ let summary=0; for(const key in counterValues){ if(counterValues.hasOwnProperty(key)){ summary+=counterValues[key]; } } return summary;}const SummaryStore=Object.assign({},EventEmitter.prototype,{ getSummary:function(){ // 实时读取CounterStore里面的值 return computeSummary(CounterStore.getCounterValues()); }, emitChange:function(){ this.emit(CHANGE_EVENT); }, addChangeListener:function(callback){ this.on(CHANGE_EVENT,callback); }, removeChangeListener:function(callback){ this.removeListener(CHANGE_EVENT,callback); }});SummaryStore.dispatchToken=AppDispatcher.register((action)=>{ if((action.type===ActionTypes.INCREMENT)||(action.type===ActionTypes.DECREMENT)){ //dispatchToken的用处: // waitFor函数:告诉Dispatcher,当前的处理必须要暂停,直到dispatchToken代表的那些已注册回调函数执行结束才能继续。 AppDispatcher.waitFor([CounterStore.dispatchToken]); SummaryStore.emitChange();}});
- 第四步:配置Counter.js组件文件内容(相当于view视图的配置)
Tips:会有多个视图(组件),所以建议建立view文件夹进行存储。
import React,{Component} from 'react';// 注意:react最新版本已经将proptypes独立出来,需要自行安装prop-types才可以使用。import PropTypes from 'prop-types';import CounterStore from '../stores/CounterStore';import * as Actions from '../Actions';export default class Counter extends Component{ constructor(props){ super(props); this.onJia=this.onJia.bind(this); this.onJian=this.onJian.bind(this); this.state={ // 实时获取到存储的值 counter:CounterStore.getCounterValues()[props.caption] } } componentDidMount(){ // 在装载完成后,给store添加事件 CounterStore.addChangeListener(this.onChange); } componentWillUnmount(){ // 在卸载前,删除store事件 CounterStore.removeChangeListener(this.onChange); } // 定义事件函数 onChange(){ // 实时从store中获取到新值 赋值给count const newCount=CounterStore.getCounterValues()[this.props.caption]; this.setState({count:newCount}); } onJia(){ // this.updateCount(true); // 分发一个action Actions.increment(this.props.caption); } onJian(){ // this.updateCount(false); // 分发一个action Actions.decrement(this.props.caption); } render(){ const btnStyle={ margin:"0 20px" }; return ( <div> <button onClick={this.onJia} style={btnStyle}>+</button> <span>{this.props.caption}:{this.state.counter}</span> <button onClick={this.onJian} style={btnStyle}>-</button> </div> ) }}Counter.propTypes={ caption:PropTypes.string.isRequired, initValue:PropTypes.number, onUpdate:PropTypes.func};Counter.defaultProps={ initValue:0, onUpdate:f=>f};
阅读全文
0 0
- react (五)Flux小结(内含MVC小知识)
- React(五):使用Flux搭建React应用程序架构
- react之flux小结
- React Native探索(五):使用Flux搭建React应用程序架构
- React.js留言板(Flux结构实现)
- React.js学习知识小结(一)
- React+Redux,从MVC到Flux
- React with TypeScript 系列(五) --Flux
- react-native-router-flux 使用详解(一)
- react Flux
- react flux
- react flux
- Linux系统知识小结(五)
- C语言知识小结(五)
- react知识小结
- react flux的坑之(一) 页面调试报错webpackJsonp is not defined
- react flux的坑之(二) 启动成功后,无法通过ip访问 webpack
- react-native使用flux
- Unity3D_直线运动
- HDU
- TP框架的介绍和使用
- c++操作符重载左边右边
- 利用SNMP4J实现 Snmp Trap 完整例子
- react (五)Flux小结(内含MVC小知识)
- APP或web测试,尤其要注意数据重复出现的情况
- 如何连接共享打印机
- 别人总结的知识图
- Swift之高级运算符与枚举
- Can't use Subversion command line client: svn Probably the path to Subversion executable is wrong. F
- Linux进入单用户模式改密或修复磁盘
- 简单的linq语法
- 29. Divide Two Integers