这篇文章来自国外一位作者的Flux For Stupid People,文章没有深究flux的具体实现,但对于想入门flux的你会有所收获。
我应该使用Flux么
- 如果你的应用有很多动态数据需要处理,你可能需要flux。
- 如果你的应用多包含静态视图,并且很少涉及到数据的存储和更新,那么flux也许不会给你带来任何好处。
什么是Flux
Flux通过事件和监听来实现了单向数据流,具体请看后文。
我们在示例代码中使用了这两个库:Flux Dispatcher和microevent.js。
官方的文档过于意识流,不适合新手学习。我们在学习时也不要将Flux与一些MVC框架相比,否则你会更加迷惑。
下面是一些Flux中提到的基本概念:
1. Your Views “Dispatch” “Actions”(视图触发事件)
dispatcher 是一个基本的事件系统,他有自己的一些规则。他会广播事件,并注册回调函数。这里我们有仅一个全局的dispatcher。你应该使用FB的Dispatcher Library。初始化很容易:
1 | var AppDispatcher = new Dispatcher(); |
假设你有一个按钮,点击之后会向列表增加一条数据。
1 | <button onClick={this.createNewItem}>New Item</button> |
点击之后,你的视图会分发一个action,其中有action的名称和增加的数据内容:
1 | createNewItem:function(evt){ |
“action”是一个核心概念。他是一个js对象,描述了我们需要做的事和我们需要的数据。如上所述,我们要做的是添加一条数据,我们需要的数据是一个名叫”Marco”的name。
Your “Store” Responds to Dispatched Actions(store触发回调)
store也是一个核心概念。我们在应用中创建一个集合,存放方法和数据,它通常是一个列表。
store是单例的,在你的整个应用中只有一个store存在:
1 | // Single object representing list data and logic |
store会对被分发的action做出处理:
1 | var ListStore = ... |
以上是一个典型的例子,介绍了Flux处理回调函数的方式。传入的参数payload包含了action的名称和需要处理的数据。
switch语句中会对相应的action做出数据的处理。
关键概念:
- store不是MVC中的model,但是它包含了models。
- 应用中数据处理只能在store中进行,这是Flux核心理念。被分发的action无法增加或者删除一条数据。
假设,你的应用中需要保存一些图片及其基本信息,那么你应该再创建一个Items,命名为ImageItems。一个数组即可代表一种数据类型了。
只有stores能够注册被分发action的回调函数。千万不要在视图中调用AppDispatcher.register。dispatcher只会单向地从视图传递数据给store。视图会针对不同的事件重新渲染。
Your Store Emits a “Change” Event(store触发change事件)
现在,store中的数据已经改变了,我们传递出数据改变的信息了。
我们将让store出发一个事件,如果在你使用了MicroEvent.js:
1 | MicroEvent.mixin( ListStore ); |
然后触发change事件:
1 | case 'new-item': |
关键概念:
- 事件触发的时候不传递数据,视图只关心是否有数据发生变化。
Your View Responds to the “Change” Event(视图接收到事件重新渲染)
视图会在数据发生变化后重新渲染,没错是重新渲染。
我们在react组件的初始化完成后为store注册监听:
1 | componentDidMount: function( ) { |
为了简单起见,我们调用forceUpdate,使视图重新渲染。
1 | listChanged : function() { |
别忘记在组件回收时,解绑监听的事件:
1 | componentWillUnmount: function( ){ |
然后来看下组件的render函数:
1 | render: function() { |
我们已经完成了整个数据,视图更新过程.当你添加一条数据的时候,视图会分发一个action,store会对action做出数据处理,并且触发一个change事件,之后视图接受到change事件并重新渲染。
但是有一个问题,每当数据更新的时候,视图将全部重新渲染,这样是否会造成效率低下?
其实并不会发生你所担心的事情,React内部构建了虚拟DOM,react会比较视图是否发生变化,实现部分的渲染,是以JS计算开销换取了dom渲染开销的方法来提升效率。
One More Thing: What The Hell Is An “Action Creator”?(Action Creator是什么鬼?)
我们在点击按钮的时候触发了一个action
1 | AppDispatcher.dispatch({ |
当我们拥有很多按钮,需要出发不同的action时,我们需要这么写看起来会比较优雅:
1 | ListActions = { |
现在增加一条数据的时候就只需要这么写:ListActions.add({name: ‘…’})
PS:不要使用 forceUpdate
文中只为了简单起见,使用了forceUpdate,正确的做法应该从store中读取数据,并且改变state,触发视图更新。