用React, Flask和SocketIO搭建在线聊天室(八)

在React的世界,初学的时候总是会遇到一些新奇的名词:Flux,Redux等。因为React并不是一个完整的前端框架,它只是一个可以创建虚拟DOM的View层。所以要想实现完整的前端框架,它就需要一些朋友帮忙,一个典型的框架就是Backbone。不过Flux和Redux这样的朋友是Facebook自己推出的,这篇文章主要介绍一下Flux这个朋友。这个在线聊天室就是根据Flux的思想架构起来的。理解了它,你就会发现js文件夹下的文件结构很清晰了。

什么是Flux

引用Flux官网的说法:

Flux is the application architecture that Facebook uses for building client-side web applications. It complements React’s composable view components by utilizing a unidirectional data flow. It’s more of a pattern rather than a formal framework, and you can start using Flux immediately without a lot of new code.

意译过来就是:

Flux是Facebook出品的,用来构建前端结构的工具。它利用单项数据流实现和React组件的无缝对接。说它是工具,但其实它只是一种模式,没必要对它产生恐惧,因为它基本没有什么新的代码。

解读

当然了,光听Facebook这么安抚,我们是不会立即消退对新事物对恐惧感的,上一张图可能更容易理解它:

用React, Flask和SocketIO搭建在线聊天室(八)

从上图可以看出,Flux就是一个组件-动作-调度-存储-组件的单向数据循环:

  • 一个组件只负责监听和启动动作(Actions),并从存储(Stores)中读取数据并更新。
  • 无论什么动作,都发送给调度员(Dispatcher)。
  • 调度员(Dispatcher)统一调配,发给需要的存储(Stores)。
  • 存储(Stores)只负责接收调度员发过来的匹配的信息,更新数据,发给它管辖的组件。

通过这种方法,Flux给了我们这样一个调度员,我们就不用再劳神在组件中管理数据的存取了,只需要把数据发送给调度员即可。

回顾文件结构

这时候,再来看在线聊天室的js文件夹,你会发现:

  • 调度员(Dospatcher)在js文件夹的根目录,方便所有组件、动作和存储调用;
  • 组件、动作和存储分别被放入对应的文件夹,保持结构的整洁;
  • 每一个组件对应的动作和存储,都会以相同文件名关联起来,方便我们调试、搜索和维护(如Rooms.js组件对应的动作文件是RoomsActions.js,对应的存储文件是RoomsStore.js)。用React, Flask和SocketIO搭建在线聊天室(八)

安装与配置Flux

有了Flux提供的调度员这个好帮手,我们要做的就是:

  • 用npm安装它:npm i -S flux
  • 在js根目录创建一个dispatcher.js文件,复制粘贴如下代码并保存:
import { Dispatcher } from 'flux';

export default new Dispatcher;

实例

现在我们已经了解了Flux,并成功安装了它,但是它究竟是如何运行的呢?我还是把Rooms的组件、动作与存储拿出来做个说明:

首先我们已经有了Rooms.js组件:https://github.com/shisaq/chat-server/blob/master/static/js/components/Rooms.js

注意看它的constructor,在20行关于State的代码:

constructor() {
    super();
    this.state = {
        rooms: RoomsStore.getAll()
    };
}

我们在这里把Rooms组件的数据托管到了RoomsStore.js中。在RoomsStore内部:

constructor() {
    super();
    this.rooms = [];
}

getAll() {
    return this.rooms;
}

这样就实现了通过在RoomsStore中添加所需的function管理数据,进而更新到Rooms组件中。

这里有几点要注意:

  1. Rooms组件既然要使用RoomsStore,就不要忘记在头部引入:import RoomsStore from '../stores/RoomsStore';
  2. RoomsStore既然要被调度员管理,就要引入调度员:import dispatcher from '../dispatcher';
  3. RoomsStore发送和监听数据是靠EventEmitter实现的,所以记得先引入EventEmitterimport { EventEmitter } from 'events';

关于EventEmitter

EventEmitter是Node.js下的东西,我们已经安装了npm,所以Node.js也早就有了。不需要安装额外的东西。它的主要作用就是:

RoomsStore的一个方法发送一个自定义名称的事件,在Rooms配置一个同名称的监听事件。通过这种方法,Rooms组件就能动态且顺利地接收到RoomsStore的数据了。这个方法其实和SocketIO很像。栗子:

RoomsStore发送一个名为addNewRoom的事件,并把数据发送给Rooms

this.emit('addNewRoom', data);

RoomscomponentWillMount()(React状态管理,渲染前要执行的代码)中添加监听事件:

RoomsStore.on('addNewRoom', (data) => {
        this.setState({
            rooms: RoomsStore.getAll()
        });
        this.props.socket.emit('join_private_room', data);
    大专栏
上一篇:vue中SocketIO的正确使用方法,并且解决跨域问题


下一篇:linux项目实战---lamp架构(十一)Zabbix云报警、API调用及数据迁移