React使用笔记6--使用flux"单向流动"你的应用
更新日期:
最近在学习使用React作为前端的框架,《React使用笔记》系列用于记录过程中的一些使用和解决方法。
本文简单介绍React Flux架构,以及记录使用flux改造当前应用的过程。
React Flux架构简介
什么是Flux
Flux是Facebook用来构建客户端Web应用的应用架构。它利用单向数据流的方式来组合React中的视图组件。
Flux是一种架构思想,专门解决软件的结构问题。它跟MVC架构是同一类东西,更像一个模式而不是一个正式的框架。
Flux基本概念
Views: 视图层
- controller-view
- 可以理解成MVC模型中的controller,它一般由应用的顶层容器充当,负责从store中获取数据并将数据传递到子组件中。
- 简单的应用一般只有一个controller-view,复杂应用中也可以有多个。
- controller-view是应用中唯一可以操作state的地方(setState())
- view(UI组件)
- ui-component职责单一只允许调用action触发事件,数据从由上层容器通过属性传递过来。
- controller-view
Action(动作):视图层发出的消息,可通过调用它来响应用户交互
- 是dispatcher提供了一个可以允许我们向store中触发分发的方法
- 包含了一个数据的payload。action生成被包含进一个语义化的辅助方法中,来发送action到dispatcher
Dispatcher(派发器):用来接收Actions、执行回调函数
- dispatcher就像是一个中央的集线器,管理着所有的数据流
- 本质上是store callback的注册表,本身并没有实际的高度功能
- 每个Store注册它自己并提供一个回调函数
Store(数据层):负责封装应用的业务逻辑跟数据的交互
- 用来存放应用的状态,一旦发生变动,就提醒Views要更新页面
- Store中包含应用所有的数据,是应用中唯一的数据发生变更的地方
- Store中没有赋值接口—所有数据变更都是由dispatcher发送到store,新的数据随着Store触发的change事件传回view
Flux数据流
- store在dispatcher中注册,并提供相应的回调。回调会接收action并把它当成自己的一个参数。
- 通过调用action来响应用户交互。
- 当action被触发,回调函数会使用switch语句来解析action中的type参数,并在合适的type下提供钩子来执行内部方法。
- action通过dispatcher来响应store中的state更新。
- store更新完成之后,会向应用中广播一个change事件,views可以选择响应事件来重新获取新的数据并更新。
参考
《Flux 架构入门教程》
《谈一谈我对 React Flux 架构的理解》
使用Flux
这里使用改造头部组件作为例子,简述使用flux过程。
目录组织
使用flux之后,目录组织如下:
这里再简单描述一下新增和改变的文件:
- actions: 存放Flux的Action文件
- components: 存放Flux的Views文件(包括Controller-Views)
- dispatcher: 存放Flux的Dispatcher文件
- stores: 存放Flux的Store文件
添加HeaderStore
在stores文件夹添加HeaderStore.js文件,封装头部相关的业务逻辑和数据交互。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36var EventEmitter = require('events').EventEmitter;
var assign = require('object-assign');
//封装头部相关的业务逻辑和数据交互
var HeaderStore = assign({}, EventEmitter.prototype, {
menus: [{
title: 'index', //title用于储存路由对应的路径
href: '?#/index', //href用于设定该菜单跳转路由
text: '首页', //text用于储存该菜单显示名称
}, {
title: 'others',
href: '?#/other',
text: '其他',
}],
usermenus: [{
click: function() {}, //click用于设置该菜单点击事件
text: '退出', //text用于储存该菜单显示名称
}],
clock: '', //clock用于保存时钟
getMenus: function() {return this.menus;}, //获取menus
getUsermenus: function() {return this.usermenus;}, //获取usermenus
getClock: function() {return this.clock;}, //获取clock
clockRender: function(callback) { //刷新时钟
let numberStandard = function(num) {
let _val = Number(num),
_num;
_num = (_val < 10) ? ('0' + _val) : ('' + _val);
return _num;
},
_date = new Date();
this.clock = _date.getFullYear() + '年' + (_date.getMonth() + 1) + '月' +
_date.getDate() + '日' + ' ' + numberStandard(_date.getHours()) + ':' + numberStandard(_date.getMinutes()) +
':' + numberStandard(_date.getSeconds());
callback(); //可使用回调触发刷新
},
});
module.exports = HeaderStore;
通过Controller-View传递数据
在components文件夹添加HeaderController.jsx和Header.jsx文件。
- HeaderController.jsx
HeaderController负责从Headerstore中获取数据并将数据传递到Header中,以及定义相关交互逻辑。
1 | import React from 'react'; //导入react组件 |
当然,如果需要更新页面的事件变多了,也可以使用event事件来进行广播哦。
- Header.jsx
Header只负责简单的页面显示即可。
1 | import React from 'react'; //导入react组件 |
添加Actions
在actions文件夹添加HeaderActions.js文件,负责发送Action到Dispatcher。1
2
3
4
5
6
7
8
9
10
11
12import AppDispatcher from '../dispatcher/AppDispatcher.js';
var HeaderActions = {
clockRender: function (callback) { //定义clockRender事件
AppDispatcher.dispatch({
actionType: 'CLOCK_RENDER', //发送Action的类型
callback: callback //携带回调事件参数
});
},
};
module.exports = HeaderActions;
注册Store到Dispatcher
在dispacther文件夹添加AppDispatcher.js文件,用来注册所有的Store。1
2
3
4
5
6
7
8
9
10
11
12
13
14import { Dispatcher } from 'flux'; //导入react组件
import HeaderStore from '../stores/HeaderStore.js'; //导入HeaderStore
var AppDispatcher = new Dispatcher();
AppDispatcher.register(function(action) {
switch (action.actionType) {
case 'CLOCK_RENDER':
HeaderStore.clockRender(action.callback); //执行clockRender事件
break;
default:
}
});
module.exports = AppDispatcher;
结束语
虽然说使用Flux会使得代码量增加了不少,但这样的架构模式也不失为一种管理应用逻辑的方法呢,使用之后应用结构也清晰很多了。
此处查看项目代码(仅包含app部分)
此处查看页面效果
码生艰难,写文不易,给我家猪囤点猫粮了喵~
查看Github有更多内容噢:https://github.com/godbasin
更欢迎来被删的前端游乐场边撸猫边学前端噢
如果你想要关注日常生活中的我,欢迎关注“牧羊的猪”公众号噢