2015年2月26日
本文将概述如何使用Flux模式构建JavaScript应用程序。让您熟悉核心助焊剂概念的材料是最少的。您应该跟随随附的入门工具包。您将需要对React的基本了解,并且最好是构建组件的一些经验。如果您不熟悉React,请阅读“React快速入门指南”。
概念
Flux是实现用户界面的架构模式。它有三个主要概念; Views , Stores and the Dispatcher (视图层,状态存储器和分发器)。还有几个次要概念; Actions , Action Types , Action Creators and Web Utils
(动作,动作的类型,动作的创建者和Web组件)。
花点时间阅读以下定义,然后按照教程。再次阅读定义,您将可以在自己的应用程序中开始使用Flux模式。
主要概念
视图是React组件。他们负责渲染接口和处理用户事件。他们的数据是从状态存储器获得的。
状态存储器管理数据。单个存储管理单个域的数据。当状态存储器更改其数据时,它通知视图。
该分发器接收新的数据,并将其传递到状态存储器。状态存储器更新其数据(如适用)并通知视图。
次要概念
动作是传递给调度程序的对象。它们包含新数据和Action Type。
动作类型是系统可以创建的操作。仅当出现特定动作类型的操作时,状态存储器才更新其数据。
动作创建者是构建Actions并将其发送到Dispatcher或Web Utils的对象。
Web组件是与外部API进行通信的对象。例如,Action Creator可以调用从服务器请求新数据。
有很多要一次吸收。我非常建议跟随入门工具包,并打印出每行,以达到最佳的理解。
免责声明:忽略常量和Web Utils的使用。这使得了解Flux更简单,一旦您已经阅读了官方示例的模式,将填写这些次要概念。
查看
获取入门工具包设置(说明在状态存储器中)后,您将在目录app.js
中找到以下文件src
。
var React = require('react');
var Comments = require('./views/comments');
var CommentForm = require('./views/comment-form');
var App = React.createClass({
render: function() {
return (
<div>
<Comments />
<CommentForm />
</div>
);
}
});
React.render(<App />, document.getElementById('app'));
这使我们对DOM的意见。忽略Comments
视图并专注于实现CommentForm
。
var React = require('react');
var CommentActionCreators = require('../actions/comment-action-creators');
var CommentForm = React.createClass({
onSubmit: function(e) {
var textNode = this.refs.text.getDOMNode();
var text = textNode.value;
textNode.value = '';
CommentActionCreators.createComment({
text: text
});
},
render: function() {
return (
<div className='comment-form'>
<textarea ref='text' />
<button onClick={this.onSubmit}>Submit</button>
</div>
);
}
});
module.exports = CommentForm;
在CommentForm
需要一个CommentActionCreators
对象,它是(顾名思义)的动作的创造者。
在表单提交中,createComment
函数传递一个comment
从textarea值构造的对象。让我们来构建这个Action Creator来接受评论。
动作
在actions
目录下创建并实现以下comment-action-creators.js
文件。
var AppDispatcher = require('../dispatcher/app-dispatcher');
module.exports = {
createComment: function(comment) {
var action = {
actionType: "CREATE_COMMENT",
comment: comment
};
AppDispatcher.dispatch(action);
}
};
该createComment
函数构建一个Action,其中包含Action类型和注释数据。此操作将传递给调度程序的dispatch
功能。
我们来构建调度程序来接受动作。
注意:我们可以在View中直接与调度程序进行通信。但是,最佳做法是使用Action Creator。它解除了我们的关注,并为Dispatcher提供了一个接口。
分发器
在dispatcher
目录下,创建并实现以下app-dispatcher.js
文件。
var Dispatcher = require('flux').Dispatcher;
module.exports = new Dispatcher();
来自Flux库的单个Dispatcher提供了该dispatch
功能。已接收的操作将传递给所有已注册的回调。这些回调是从状态存储器提供的。
注意:由于Dispatcher实现被隐藏,因此这是一个到源的链接。
状态存储器
在stores
目录下,创建并实现以下comment-store.js
文件。
var AppDispatcher = require('../dispatcher/app-dispatcher');
var EventEmitter = require('events').EventEmitter;
var assign = require('object-assign');
var comments = [];
var CommentStore = assign({}, EventEmitter.prototype, {
emitChange: function() {
this.emit('change');
},
addChangeListener: function(callback) {
this.on('change', callback);
},
removeChangeListener: function(callback) {
this.removeListener('change', callback);
},
getAll: function() {
return comments;
}
});
AppDispatcher.register(function(action) {
switch(action.actionType) {
case "CREATE_COMMENT":
comments.push(action.comment);
CommentStore.emitChange();
break;
default:
}
});
module.exports = CommentStore;
有两段代码; 状态存储器创建和状态存储器注册(与调度程序)。
通过合并EventEmitter.prototype
对象和自定义对象创建状态存储器,类似于Dispatcher创建。该EventEmitter.prototype能订阅回调后的事件,并让
状态存储器发出事件。
自定义对象定义用于订阅和取消订阅change
事件的公共功能。它还定义了getAll
返回comments
数据的函数。
接下来,Store将向Dispatcher注册一个函数。当Dispatcher调用dispatch
它将其参数(即Action)传递给每个已注册的回调函数。
在这种情况下,当使用Action Type 调用Action时CREATE_COMMENT
,CommentStore
将将数据推入其注释数组并调用该emitChange
函数。
现在我们需要一个视图来显示状态存储器的评论并订阅更改。
在views
目录中查找comments.js
文件。修改它以匹配以下。
var React = require('react');
var CommentStore = require('../stores/comment-store');
function getStateFromStore() {
return {
comments: CommentStore.getAll()
}
}
var Comments = React.createClass({
onChange: function() {
this.setState(getStateFromStore());
},
getInitialState: function() {
return getStateFromStore();
},
componentDidMount: function() {
CommentStore.addChangeListener(this.onChange);
},
componentWillUnmount: function() {
CommentStore.removeChangeListener(this.onChange);
},
render: function() {
var comments = this.state.comments.map(function(comment, index) {
return (
<div className='comment' key={'comment-' + index}>
{comment.text}
</div>
)
});
return (
<div className='comments'>
{comments}
</div>
);
},
});
module.exports = Comments;
大多数这是熟悉的React代码,增加了需要CommentStore
和几个Store相关的附加功能。
该getStateFromStores
功能从状态存储器检索评论数据。这被设置为其中的初始组件状态getInitialState
。
里面componentDidMount
的onChange
函数传递到存储的addChangeListener
功能。当状态存储器发出的change
事件onChange
现在将触发,将组件的状态设置为已更新的存储数据。
最后从状态存储器componentWillUnmount
中删除该onChange
功能。
结论
我们现在有一个工作的Flux应用程序,并触及了模式的每个核心概念; Views , Stores and the Dispatcher (视图层,状态存储器和分发器)。
- 当用户提交评论时,视图调用Action Creator。
- Action Creator构建一个Action并将其传递给Dispatcher。
- Dispatcher将Action发送到已注册的Store回调。
- Stores更新其注释的数据并发出更改事件。
- 视图从Stores更新其状态并重新呈现。
这是Flux的精髓。Dispatcher将数据发送到更新并通知其Views的所有Stores。