React入门与进阶之Flux
wmdk3776
8年前
<h2><strong>React入门与进阶之Flux</strong></h2> <p>本篇我们详细介绍为React设计的架构模式Flux。Flux为React提供了一种单向数据流模式,使用此模式能够很方便的监控数据变化的原因和过程。</p> <h2><strong>Flux初识</strong></h2> <p>Flux是非死book用来创建客户端web应用的一种架构模式,它使用单向数据流方式实现了React组件的复合和通信。</p> <p>一个Flux应用主要包含三大部分:dispatcher,store和views(即React Component)。如果细分一下,也可以分为四部分:dispatcher,action,store和views。Flux模式下各部分均相互独立。</p> <h3><strong>数据流</strong></h3> <p>贯穿Flux的一个核心概念是单向数据流(undirectional data flow),盗个官方图:</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/ecf4e33fd65104135ba4284986f61da0.png"></p> <p>如图,Flux各部分相互独立,使用Action creators辅助函数创建一个action,提供给dispatcher;在store中给dispatcher注册回调函数,dispatcher通过回调函数将每个action分发给所有store;store根据action进行更新操作,并发布特定变化事件,views订阅该特定变化事件,并注册回调函数;特定变化事件触发后回调函数执行,该函数可以接收数据参数并将数据传递给React组件,调用setState()方法,整个组件进行重新渲染。</p> <h2><strong>Action</strong></h2> <p>Action creator是一个辅助函数,该辅助函数创建一个action,且将该action传递给dispatcher;该函数接收一个对象参数,该对象拥有type属性,表示所创建action的类型,也可以包含其他数据。</p> <p>dispatcher提供一个方法,允许我们触发一个dispatch,该方法接收一个对象做参数,随后将这个对象分发给所有store,我们把该对象叫做action,此方法就是我们通常说的action creator。</p> <pre> <code class="language-javascript">var NotingDispatcher = require('../dispatcher/NotingDispatcher'); var _CONSTANT = require('../commons/variables'); var NotingActions = { create: function(content) { NotingDispatcher.dispatch({ type: _CONSTANT.CREATE, content: content }); } };</code></pre> <p>代码中,使用dispatcher提供的dispatch方法,创建一个action给dispatcher,该action对象有type属性代表action类型,也可以有其他任何属性,如此处的noting内容属性。</p> <h2><strong>Dispatcher</strong></h2> <p>Dispatcher提供一个register方法,该方法允许我们为该dispatcher注册一个回调函数,该回调函数接收一个action参数,在回调中将action传递给store。</p> <p>Diapatcher还提供一个dispatch方法,在action中触发注册的回调函数。</p> <p>dispatcher是Flux应用管理数据流的中心线。</p> <p>注:dispatcher允许我们将每一个action分发给所有store。</p> <pre> <code class="language-javascript"> var NotingDispatcher = require('flux').Dispatcher;</code></pre> <p>对于dispatcher,我们只需要使用Flux提供的Dispatcher;</p> <h2><strong>Store</strong></h2> <p>store主要负责给dispatcher注册回调函数,在回调函数中根据传入的action进行相应处理,更新store(更新应用状态),并发布一个变化事件,该事件在views中触发对该事件的订阅,可以通过事件回调函数将新的应用状态作为参数传入views。</p> <p>在Flux应用中,我们在store内维护应用状态和逻辑。</p> <p>注:store中的应用状态不是React组件中所说的state。</p> <h3><strong>发布订阅模式</strong></h3> <p>Flux store中使用发布订阅模式维护,传递应用状态,这里使用events模块提供发布订阅功能的实现。</p> <pre> <code class="language-javascript"> var EventEmitter = require('events').EventEmitter; var NotingDispatcher = require('../dispatcher/NotingDispatcher'); var Utils = require('../commons/utils'); var notings = require('../commons/NotingData'); var _CONSTANT = require('../commons/variables'); var NotingStore = Utils.extend({}, EventEmitter.prototype, { create: function(content) { var id = Utils.makeUID(); notings[id] = { id: id, content: content }; }, getAllNotings: function() { return notings; }, emitChange: function() { this.emit(_CONSTANT.CHANGEEVENT); }, bindChangeEvent: function(callback) { this.on(_CONSTANT.CHANGEEVENT, callback); }, removeChangeEvent: function(callback) { this.removeListener(_CONSTANT.CHANGEEVENT, callback); } }); NotingDispatcher.register(function(action) { var content = action && action.content; switch(action.type) { case _CONSTANT.CREATE: if (content !== '') { NotingStore.create(content); NotingStore.emitChange(); } break; } });</code></pre> <p>在store中,我们使用dispatcher提供的register方法为dispatcher注册回调函数,回调函数接收一个action,根据action类型和数据做相应的逻辑处理。我们也可以看到,整个应用的状态(主要指数据)在store中进行维护,并通过发布/订阅模式结合回调函数的方式将应用状态的更新发布到views,使得views能将数据传递给React组件树,改变组件状态。</p> <h2><strong>Views</strong></h2> <p>Flux中的views负责在组件渲染后监听(订阅)由store发布的变化事件,在事件回调中,新的数据作为参数传入,然后调用React组件的setState()方法,更新组件状态,触发组件的重新渲染。</p> <p>views从store接收数据并将数据传给组件树,组件树根据传入的数据更新state。</p> <p>注:Flux的views是一种特殊的控制视图(control-views)。</p> <pre> <code class="language-javascript"> var React = require('react'); var NotingStore = require('../stores/NotingStore'); var NotingList = require('./NotingList'); function getNotingState() { console.log(NotingStore.getAllNotings()); return { notings: NotingStore.getAllNotings() }; } var NotingApp = React.createClass({ _onChange: function() { this.setState(getNotingState()); }, getInitialState: function() { return getNotingState(); }, componentDidMount: function() { NotingStore.bindChangeEvent(this._onChange); }, componentWillUnMount: function() { NotingStore.removeChangeEvent(this._onChange); }, render: function() { return ( <div> <h2>React Noting</h2> <NotingList notings={this.state.notings}></NotingList> </div> ); } });</code></pre> <p>如代码中,在组件生命周期函数componentDidMount即组件渲染完成后触发订阅stor管理的变化事件,在组件卸载的时候取消订阅(componentWillUnMount函数中实现)。</p> <p> </p> <p> </p> <p> </p> <p>来自:http://blog.codingplayboy.com/2016/09/25/react_flux/</p> <p> </p>