第 13 章:使用 Flux 构建可扩展的 UI
Flux 架构通过单向数据流和显式状态管理,帮助开发者构建高可扩展性、易维护的现代 Web UI。本章将系统介绍 Flux 的核心原理、组件分层与代码实践,并结合 Go 微服务实现云原生前端架构。
引言
在上一章中,我们初步了解了 React 框架及其单向数据流理念。本章将进一步探讨 Flux 架构模式,重点介绍如何通过 Flux 实现复杂 UI 的可扩展性和高性能,并结合 Go 微服务构建完整的前后端系统。
本章主要内容包括:
- Flux 架构模式与核心组件解析
- 使用 Flux 构建高流量场景下的应用程序
- 代码分层与实践示例
- 总结与参考文献
Flux 架构模式简介
Flux 并非具体实现或库,而是一种架构模式,类似于 MVC。Flux 基于单向数据流,强调将数据和状态从视图中分离出来,通过 dispatcher、store、action、source 等组件实现显式的数据流管理。
Flux 核心组件说明
Flux 架构包含以下核心组件:
- dispatcher(分派器):负责将载荷广播到注册的回调函数,协调系统中的数据流。
- store(数据仓库):存储应用状态,响应 dispatcher 派发的事件并触发视图渲染。
- view(视图):通常为 React 组件,负责渲染 UI 并响应 store 状态变化。
- action(动作):由用户或系统事件触发,描述状态变更的意图。
- source(数据源):与后端服务通信,获取或提交数据,解耦 store 与实际数据。
下图展示了 Flux 架构的数据流关系:

数据始终单向流动:action → dispatcher → store → view。
Flux 架构的优势与复杂性
Flux 通过显式分层和单向数据流,提升了系统的可维护性和可扩展性。虽然组件数量较多,但每个组件职责单一,便于故障排查和功能扩展。相比“魔术”式的双向绑定框架,Flux 更适合构建复杂、可测试的云原生前端系统。
创建 Flux 应用程序
本节以僵尸爆发监控应用为例,展示如何通过 Flux 架构优化 React 应用的状态管理和组件设计。
App 组件重构示例
通过 Flux 分离状态管理,App 组件变得简洁易维护:
// filepath: App.jsx
import React from 'react';
import Outbreaks from "./Outbreaks"
import OutbreakStore from '../stores/OutbreakStore'
import OutbreakActions from '../actions/OutbreakActions'
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = OutbreakStore.getState();
}
componentDidMount() {
OutbreakStore.listen(this.storeChanged);
OutbreakStore.fetchOutbreak();
}
componentWillUnmount() {
OutbreakStore.unlisten(this.storeChanged);
}
storeChanged = (state) => {
this.setState(state);
};
addOutbreak = (event) => {
OutbreakActions.addOutbreak();
}
render() {
const outbreaks = this.state.outbreaks;
return (
<div>
<button onClick={this.addOutbreak}>New Report</button>
<Outbreaks outbreaks={outbreaks}/>
</div>
);
}
}
组件挂载时监听 store 状态变化,初始数据通过 fetchOutbreak 获取,事件处理通过 action 分发。
Action 层实现示例
Action 层定义所有状态变更的意图:
// filepath: OutbreakActions.js
import alt from '../lib/alt';
import uuid from 'node-uuid';
class OutbreakActions {
updateOutbreak(outbreak) { return outbreak; }
fetchOutbreak() { return []; }
deleteOutbreak(outbreak) { return outbreak; }
changeOutbreak(outbreak) { return outbreak; }
outbreakFailed(errorMessage) { return errorMessage; }
addOutbreak() {
var d = new Date();
var datestring = ("0" + d.getDate()).slice(-2) + "-" +
("0" + (d.getMonth() + 1)).slice(-2) + "-" +
d.getFullYear() + " " + ("0" + d.getHours()).slice(-2) + ":" +
("0" + d.getMinutes()).slice(-2);
var newOutbreak = {
id: uuid.v4(),
origin: "Station Gamma",
severity: "Yellow",
description: "This was bad",
date: datestring
};
return newOutbreak;
}
}
export default alt.createActions(OutbreakActions);
Action 只描述意图,不直接操作状态。
Source 层实现示例
Source 层负责与后端服务或模拟数据通信:
// filepath: OutbreakSource.js
import uuid from 'node-uuid';
import OutbreakActions from '../actions/OutbreakActions'
var mockData = [
{
id: uuid.v4(),
origin: "Station Gamma",
severity: "Yellow",
description: "This was bad",
date: "03-04-2016 12:00"
}
];
const OutbreakSource = {
fetchOutbreak() {
return {
remote() {
return new Promise(function (resolve, reject) {
resolve(mockData);
})
},
local() { return null; },
success: OutbreakActions.updateOutbreak,
error: OutbreakActions.outbreakFailed,
loading: OutbreakActions.fetchOutbreak
}
}
};
export default OutbreakSource;
Source 层可灵活切换为真实 RESTful 服务或模拟数据。
Store 层实现示例
Store 层负责持久化状态并响应 action:
// filepath: OutbreakStore.js
import alt from '../lib/alt';
import OutbreakSource from '../sources/OutbreakSource'
import OutbreakActions from '../actions/OutbreakActions';
class OutbreakStore {
constructor() {
this.outbreaks = [];
this.errorMessage = null;
this.bindListeners({
handleUpdateOutbreaks: OutbreakActions.UPDATE_OUTBREAK,
handleFetchOutbreak: OutbreakActions.FETCH_OUTBREAK,
handleOutbreakFailed: OutbreakActions.OUTBREAK_FAILED,
handleChangeOutbreak: OutbreakActions.CHANGE_OUTBREAK,
handleDeleteOutbreak: OutbreakActions.DELETE_OUTBREAK,
handleAddOutbreak: OutbreakActions.ADD_OUTBREAK
});
this.exportAsync(OutbreakSource)
}
handleDeleteOutbreak(outbreak) {
this.outbreaks = this.outbreaks.filter(target => target.id !== outbreak.id)
}
handleAddOutbreak(outbreak) {
this.outbreaks = this.outbreaks.concat([outbreak]);
}
handleChangeOutbreak(outbreak) {
// 可扩展为复杂状态变更
}
handleUpdateOutbreaks(outbreaks) {
this.outbreaks = outbreaks;
this.errorMessage = null;
}
handleFetchOutbreak() {
this.outbreaks = [];
}
handleOutbreakFailed(errorMessage) {
this.errorMessage = errorMessage;
}
}
export default alt.createStore(OutbreakStore, 'OutbreakStore');
Store 通过 exportAsync 绑定 source,实现异步数据获取与状态管理。
组件层响应示例
组件通过 action 触发状态变更,store 监听并更新视图:
// filepath: OutbreakReport.jsx
import React from 'react';
import OutbreakActions from '../actions/OutbreakActions';
export default class OutbreakReport extends React.Component {
constructor(props) {
super(props);
this.state = { editing: false };
}
render() {
if (this.state.editing) {
return this.renderEdit();
}
return this.renderOutbreakReport();
}
renderEdit = () => (
<div>
<div className="date">{this.props.outbreak.date}</div>
<div className="origin">{this.props.outbreak.origin}</div>
<div className="severity">{this.props.outbreak.severity}</div>
<div className="description">
<input
type="text"
autoFocus={true}
defaultValue={this.props.outbreak.description}
onBlur={this.finishEdit}
onKeyPress={this.checkEnter}
/>
</div>
</div>
);
edit = () => {
this.setState({ editing: true });
};
checkEnter = (e) => {
if (e.key === 'Enter') {
this.finishEdit(e);
}
};
finishEdit = (e) => {
const value = e.target.value;
this.setState({ editing: false });
if (!value.trim()) {
return;
}
this.props.outbreak.description = value;
OutbreakActions.changeOutbreak(this.props.outbreak);
}
onDelete = (e) => {
OutbreakActions.deleteOutbreak(this.props.outbreak);
}
renderOutbreakReport = () => (
<div>
<div className="date">{this.props.outbreak.date}</div>
<div className="origin">{this.props.outbreak.origin}</div>
<div className="severity">{this.props.outbreak.severity}</div>
<div className="description" onClick={this.edit}>
{this.props.outbreak.description}
</div>
{this.renderDelete()}
</div>
);
renderDelete = () => (
<button className="delete-outbreak" onClick={this.onDelete}>X</button>
);
}
组件交互通过 action 触发,store 统一管理状态,提升可维护性和扩展性。
构建与运行 Flux 应用
安装依赖并启动开发服务器:
npm install
npm run watch
# 访问 http://localhost:8080
构建生产版本并结合 Go 服务运行:
npm run build
go build
./flux-zombieoutbreak
# [negroni] listening on :8100
也可通过 Docker 镜像快速部署:
docker run -p 8100:8100 -e WEBROOT=/pipeline/sourcecloudnativego/flux-zombieoutbreak
总结
本章系统介绍了 Flux 架构的核心原理、组件分层与代码实践,并结合 Go 微服务实现云原生前端架构。通过单向数据流和显式状态管理,开发者可高效构建可扩展、易维护的现代 Web UI。建议结合实际项目,深入理解 Flux 与后端服务的集成模式,为后续复杂系统开发打下坚实基础。
参考文献
- Flux 架构模式 - facebook.github.io
- Alt.js 官方文档 - github.com
- React 官方文档 - react.dev
- Node.js 官方文档 - nodejs.org
- Webpack 官方文档 - webpack.js.org
- Building Microservices - oreilly.com