FluxDemo学习
1. 基本概念
首先,Flux将一个应用分为了四个部门
View: 试图层
Action:方法层,里面有各种方法
Dispatcher:分发器,里面放了很多Actions,然后可以执行他们
-
Store:数据层,要不叫持久层?通过这个来保存应用的各种状态,然后他变化了,View也会发生变化
单向数据流———流程图:
graph LR;
Action-->Dispatcher;
Dispatcher-->Store;
Store-->View;
View-->Action
这就感觉像是一个圈,但是一般来说,是这样的
当用户点击一个View上的一个按钮的时候,会发出一个Action
然后Dispatcher会收到这个Action,然后叫Store去把数据更新了
Store更新了之后呢,就会叫View把页面也更新了
差不多就是这么个流程了。。。
[图片上传中...(image.png-58a622-1523635613909-0)]
2. 查看Demo
然后我们去看下demo项目
好吧,看到后缀是jsx我就懵了,jsx又是什么格式呢~,这个下次再讨论
var React = require('react');
var ReactDOM = require('react-dom');
var MyButtonController = require('./components/MyButtonController');
ReactDOM.render(
,
document.querySelector('#example')
);
这个按钮组件的名字我们可以看出,我的 按钮 控制器
这里采用的是React的controller view模式,只是用来进行状态的保存用的
MyButtonController组件呢,主要通过他来对各种事件进行调用。
我们可以看到,在这个组件里面,他有好几个function,在前面还有componentDidMount(组件初始化后执行一次),componentWillUnmount(移除的时候执行一次),在componentDidMount下面给ListStor中的addChangeListener传递进去了一个回调函数,也就是对ListStore进行操作的函数
...
componentDidMount: function() {
ListStore.addChangeListener(this._onChange);
},
...
createNewItem: function (event) {
ButtonActions.addNewItem('new item');
},
render: function() {
return ;
下面则一个MyButton组件,一共传递两个参数,一个是items(项目),一个的点击后的回调函数。
var React = require('react');
var MyButton = function(props) {
var items = props.items;
var itemHtml = items.map(function (listItem, i) {
return {listItem} ;
});
return
{itemHtml}
;
};
module.exports = MyButton;
这里可以看出,MyButton组件相当于一个纯组件,或者叫做一个“展示型”组件
React可以分为两种,一种是容器型组件,一种是展示型组件,要区分他们的话,主要是看是否有数据操作。比如说上面的MyButtonController组件,他就是一个容器型组件,它于Store进行了操作。
像上面的MyButton组件,他就执行了几个简单的操作,一个是你给我数据,我给你渲染出ul,一个是点击我时候,会触发你传递过来的createNewItem函数,用来调用Action中的addNewItem方法
createNewItem: function (event) {
ButtonActions.addNewItem('new item');
},
addNewItem则会告诉Dispatcher中的分发器去分发这个Action
addNewItem: function (text) {
AppDispatcher.dispatch({
actionType: 'ADD_NEW_ITEM',
text: text
});
},
而在Dispatcher中呢,则会相应的对数据进行更新:
switch(action.actionType) {
case 'ADD_NEW_ITEM':
ListStore.addNewItemHandler(action.text);
ListStore.emitChange();
break;
default:
// no op
}
3. Action
每一个Action都是一个对象,包含一个actionTyp属性(说明动作的类型)和一些其他属性(用来传递数据)。---阮一峰
4. Dispatcher
Dispatcher的作用就是把Action派发到Store中去,是一个单例,它就负责联系View和Store。告诉他们两个Action应该怎么扔。
我们在使用的时候,会需要引入一个AppDispatcher.js,然后new一个实例
var Dispatcher = require('flux').Dispatcher;
var AppDispatcher = new Dispatcher();
并且在Dispatcher中,只能用来进行派发Action,不应该有其他的操作。
5. Store
Store其实就是MVC中的Model里面有各种get啊set啊之类的操作。
在这个demo中,有一个ListStore来进行数据的存储。
getAll: function () {
return this.items;
},
addNewItemHandler: 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);
}
方法名 | 作用 |
---|---|
ListStore.items | 保存数据,也就是保存里面的条目 |
ListStore.getAll | 获取所有的数据条目 |
ListStore.addNewItemHandler | 新增一个新的条目 |
ListStore.emitChange | 发射一个“change”事件 |
ListStore.addChangeListener | 添加改变监听 |
ListStore.removeChangeListener | 添加移除监听 |
在上面的代码中,ListStore继承了EventEmitter.prototype,所以就可以使用ListStore.on()和ListStore.emit()来监听和触发事件了。
Store更新后,会发出一个change事件,说明状态改变了,View监听后,查询新的状态,并更新页面
6. View
那么关于View呢,在MyButtonController组件中,它是可以监听change事件的。
在组件创建的时候,会触发一个addChangeListener来进行change事件的监听,之后,在组件移除的时候,也会触发removeChangeListener事件。。。
7.总结
看了他这种写法,感觉Action,Service,Dao ~~~
真的好像啊,Action里面有着各种各样的方法,当用户点击按钮的时候,触发Action事件,当然,这个Action是通过Controller来进行触发的,也就是容器组件。
触发后,Action调用AppDispatcher中的分发器,来进行事件的具体实现,也就是相当于Service层
service层的作用:
- 封装通用的业务逻辑,操作。
如一些数据的检验,可以通用处理。- 与数据层的交互。
- 其他请求:如远程服务获取数据,如第三方api等。
相对于MVC中的直接和数据交互,Flux中的Store则更像是一个缓存,看官方的流程图介绍,在与后端进行交互的时候,是在Action Creators进行控制的。。。
感觉就像是,前端的Action,和后端的Action进行数据交互,然后,拿到数据后,前端把数据调用AppDispatcher来进行数据分发,用Store来进行数据操作,从而影响View。
而后端Action接收数据后,交给Service层进行业务处理,之后给Dao层保存进行数据库。
我看到关于API访问放在哪的讨论,这个先不管了,我们按照官方的图进行操作吧。
别人的流程图:
graph LR;
Action-->Dispatcher;
Dispatcher-->Store;
Store-->WebApi;
WebApi-->Store;
Store-->View;
View-->Action
流程图来源
https://segmentfault.com/q/1010000002867736