React入門與進階之Flux
React入門與進階之Flux
本篇我們詳細介紹為React設計的架構模式Flux。Flux為React提供了一種單向數據流模式,使用此模式能夠很方便的監控數據變化的原因和過程。
Flux初識
Flux是非死book用來創建客戶端web應用的一種架構模式,它使用單向數據流方式實現了React組件的復合和通信。
一個Flux應用主要包含三大部分:dispatcher,store和views(即React Component)。如果細分一下,也可以分為四部分:dispatcher,action,store和views。Flux模式下各部分均相互獨立。
數據流
貫穿Flux的一個核心概念是單向數據流(undirectional data flow),盜個官方圖:
如圖,Flux各部分相互獨立,使用Action creators輔助函數創建一個action,提供給dispatcher;在store中給dispatcher注冊回調函數,dispatcher通過回調函數將每個action分發給所有store;store根據action進行更新操作,并發布特定變化事件,views訂閱該特定變化事件,并注冊回調函數;特定變化事件觸發后回調函數執行,該函數可以接收數據參數并將數據傳遞給React組件,調用setState()方法,整個組件進行重新渲染。
Action
Action creator是一個輔助函數,該輔助函數創建一個action,且將該action傳遞給dispatcher;該函數接收一個對象參數,該對象擁有type屬性,表示所創建action的類型,也可以包含其他數據。
dispatcher提供一個方法,允許我們觸發一個dispatch,該方法接收一個對象做參數,隨后將這個對象分發給所有store,我們把該對象叫做action,此方法就是我們通常說的action creator。
var NotingDispatcher = require('../dispatcher/NotingDispatcher');
var _CONSTANT = require('../commons/variables');
var NotingActions = {
create: function(content) {
NotingDispatcher.dispatch({
type: _CONSTANT.CREATE,
content: content
});
}
};
代碼中,使用dispatcher提供的dispatch方法,創建一個action給dispatcher,該action對象有type屬性代表action類型,也可以有其他任何屬性,如此處的noting內容屬性。
Dispatcher
Dispatcher提供一個register方法,該方法允許我們為該dispatcher注冊一個回調函數,該回調函數接收一個action參數,在回調中將action傳遞給store。
Diapatcher還提供一個dispatch方法,在action中觸發注冊的回調函數。
dispatcher是Flux應用管理數據流的中心線。
注:dispatcher允許我們將每一個action分發給所有store。
var NotingDispatcher = require('flux').Dispatcher;
對于dispatcher,我們只需要使用Flux提供的Dispatcher;
Store
store主要負責給dispatcher注冊回調函數,在回調函數中根據傳入的action進行相應處理,更新store(更新應用狀態),并發布一個變化事件,該事件在views中觸發對該事件的訂閱,可以通過事件回調函數將新的應用狀態作為參數傳入views。
在Flux應用中,我們在store內維護應用狀態和邏輯。
注:store中的應用狀態不是React組件中所說的state。
發布訂閱模式
Flux store中使用發布訂閱模式維護,傳遞應用狀態,這里使用events模塊提供發布訂閱功能的實現。
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>
在store中,我們使用dispatcher提供的register方法為dispatcher注冊回調函數,回調函數接收一個action,根據action類型和數據做相應的邏輯處理。我們也可以看到,整個應用的狀態(主要指數據)在store中進行維護,并通過發布/訂閱模式結合回調函數的方式將應用狀態的更新發布到views,使得views能將數據傳遞給React組件樹,改變組件狀態。
Views
Flux中的views負責在組件渲染后監聽(訂閱)由store發布的變化事件,在事件回調中,新的數據作為參數傳入,然后調用React組件的setState()方法,更新組件狀態,觸發組件的重新渲染。
views從store接收數據并將數據傳給組件樹,組件樹根據傳入的數據更新state。
注:Flux的views是一種特殊的控制視圖(control-views)。
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>
);
}
});
如代碼中,在組件生命周期函數componentDidMount即組件渲染完成后觸發訂閱stor管理的變化事件,在組件卸載的時候取消訂閱(componentWillUnMount函數中實現)。
來自:http://blog.codingplayboy.com/2016/09/25/react_flux/