Flux框架

Flux用来解决React在结构上的问题,从Flux也衍生了Redux,Flux也类似MVC这一类的架构,Flux最大特点就是单向数据流动

1.基本概念

Flux框架_第1张图片
flux流程

这是Flux在GitHub上文档中所提供的流程展示图,里面有四个核心的东西

Action:动作,视图层发出的动作,类似事件
Dispatcher:派发器,接受Action,全局唯一,相当于C
Store:存储层,相当于M,数据变化,会让View层对应修改,负责存储和处理数据相关逻辑
View:视图层,相当于V

整个流程如下
1.从用户操作页面开始,发出Action
2.Dispatcher接受Action,然后派发Action,找到对应的Store
3.Store进行更新,发出一个change事件
4.页面接受change,更新界面
这就是一个完整单向的数据流动过程,任何过程都不会发生双向数据流动

2.Action

整个过程从Action开始,Action是一个JS对象,用来描述我们要干什么,需要什么样的数据,可以写一个Action.js文件,在这个文件里,对所有Action进行汇总,Flux只要加一个新的功能,就要对应加一个Action类型,这就像MVC中如果要添加新的功能添加新的Controller一样,在Flux里,就是添加新的Action.

export const addNum = (result) => {
  AppDispatcher.dispatch({
    actionName: "add",
    counterCaption: result
  });
};

定一个对外使用的函数,这个函数目的就是点击按钮+1,通过页面点击事件发出的Action而,触发事件的View,还是正常绑定事件,只是在对应事件的具体实现,需要找到Action里对应的函数,然后进行调用

import * as Actions from '../Actions.js';
class Son extends Component {
  onClickAddButton() {
    Actions.addNum("add");
  }
}

当然我简化了整个过程,这样就完成了事件的触发,接下来开始执行回调函数里面的内容了,首先我们引入了AppDispatcher.js文件,它创造了一个唯一的Dispatcher对象,类似于单例,通过它来发送和接管Action.
AppDispatcher.dispatch相当于发送了一个消息,这个消息包含了需要发送的内容,也就是需要传的值,一般都会有actionName这样的字段,标明当前Action代表了什么样的操作,名随便,然后其他字段可以对应要传的值.

3.Dispatcher

在代码里,Dispatcher对应的AppDispatcher.js不需要写什么,就返回一个默认的Dispatcher对象

import {Dispatcher} from 'flux';
export default new Dispatcher();

Dispatcher提供的API也不是很多,一共5个方法
1.dispatch:用来发送消息,包含要传的数据,Action的参数
2.register(function callback):注册一个接受消息的接收器,可以接受到dispatch发送的消息,Stores自己需求,完成对应数据的操作
3.unregister:跟注册相应的方法,移除毁掉函数
4.isDispatching:boolean类型的返回值,是否目前正在调用的dispatcher
5.waitFor(array ids):有的时候在一个过程中注册了几个监听器,但是就怕出现意外,因为顺序上的混乱造成bug,所以为了避免这个问题就可以使用waitFor来控制.这个方法需要一个数组,这个数组里的元素都是dispatchToken,也就是注册的监听器,会告诉Dispatcher当前的处理必须暂停,直到这些已经注册的监听都执行结束才会继续,这样就避免了因为顺序而造成的不必要的错误
注册这部分代码要写在Stores

import AppDispatcher from '../AppDispatcher.js';
CounterStore.dispatchToken = AppDispatcher.register((action) => {
  if (action.actionName === "add") {
    counterValues[action.counterCaption] ++;
  } else if (action.actionName === "sub") {
    counterValues[action.counterCaption] --;
  }
});

CounterStore是一个计数器类,添加了dispatchToken用来保存注册的监听器,action用来接收发射器传递的数据,根据对应的action事件类型进行对应的操作,而且这个文件如果被其他文件inport之后,可以通过CounterStore.dispatchToken找到对应的监听器,这样就能用在waitFor这个方法里了

4.Store

Store用来存储应用对应状态,根据接收dispatch对应的状态,更改View的显示状态,而监听整个变化的过程就需要使用EventEmitter来帮助实现.EventEmitter的核心功能就是事件触发和事件监听.

import {EventEmitter} from 'events';
const CounterStore = Object.assign({}, EventEmitter.prototype, {
    getCounterValues: function() {
        return counterValues;
    },
    emitChange: function() {
        this.emit('changed');
    },
    addChangeListener: function(callback) {
        this.on('changed', callback);
    },
    removeChangeListener: function(callback) {
        this.removeListener('changed', callback);
    }
});

引完库文件之后,通过代码拷贝创建了一个CounterStore对象,而拷贝的内容就是EventEmitter.prototype,这样就可以使用prototype提供的响应方法.
1.getCounterValues函数是为了获取当前计数器初始值的,这个跟EventEmitter无关.
2.emitChange:这个函数调用了emit,这是EventEmitter提供的功能,用来广播一个特定事件,第一个参数是事件名称,字符串.这个方法是一个做汇总的模块用的.
3.addChangeListener:添加监听,用EventEmitter提供的on进行绑定,第一个参数是事件名称,第二个参数是对应的回调函数,这个函数将在View界面传过来
4.removeChangeListener:移除,跟on功能想法,但是删除对应的回调函数要和添加的时候是同一个,这跟JQ移除事件的要求是相同的

5.View

通过了Store,就要通过View来具体呈现,

import CounterStore from '../stores/CounterStore.js';
class Son extends Component {
    componentDidMount() {
        CounterStore.addChangeListener(this.onChange);
    }
    componentWillUnmount() {
        CounterStore.removeChangeListener(this.onChange);
    }
    onChange() {
        // 更改数据内容
    }
}

在装载和摧毁两个周期调用监听的函数,同时设置回调函数onChange,onChange里就对应了对数据的操作.在View的时候,只能使用Store的get方法,而Store也没有set方法就是为了防止V直接去修改M上的数据,如果想改Store的数据,可以在发送action,重新一个新的流程,避免了传统MVC数据上的混乱

整个过程从点击按钮开始,到最后数字+1结束,完成了一个闭合的操作

你可能感兴趣的:(Flux框架)