Introduction
flux應用架構如下圖所示,本文並不是講述怎么立即做一個酷炫的應用,而是講述如何依照這種框架,來進行代碼的組織。
我們先把這個流程轉述為文字:拋開與webAPI的交互不談,以后的文章再介紹。
flux應用的數據流是單向的,從我們之前最熟悉的React組件看起,它們構成了上圖中的React Views。用戶交互可以使得Action Creators創建Action,交由Dispatcher分發。根據已注冊的Store信息,Dispathcer管理依賴,完成分發,而Store會觸發數據改變的事件,偵聽該事件的React Views即會進行Store Queries,拿到數據。
本文以完成下圖的功能為例,一個可以添加item的表單。如果不套flux用的代碼少的多,但是,這樣的例子適合用於講解flux而非專注於其它細節(復雜應用將更偏重於React 組件的設計,於本文中心偏離)。
源碼已經上傳:https://github.com/EcutDavid/fluxDemo
搭建目錄,文件結構
mkdir script && cd script
mkdir actions components dispatcher stores constants
cd ..
touch entry.js index.html webpack.config.js
關於webpack,博主的webpack系列文章已經介紹,再此,不再贅述。
安裝moudles(關於moudles的選型,仁者見仁,智者見智,無需拘束於以下的例子)。
npm init
npm install babel-loader css-loader style-loader flux react keymirror events obejct-assign --save
Dispatcher
flux中, Dispatcher是單例的,所以,直接向下面代碼一樣返回一個實例。之后,Action與Store都會用到它們。
script/dispatcher/dispatcher.js
var Dispatcher = require('flux').Dispatcher;
module.exports = new Dispatcher();
Action
實現一個枚舉,用於定義所有的Action類型,借助於keymirror實現
script/constants/appConstants.js
var keyMirror = require('keymirror');
module.exports = new keyMirror({
CREATE: null
});
ActionCreator要借助dispatcher來分發action。
script/actions/appActionCreator.js
"use strict"
var dispatcher = require('../dispatcher/dispatcher');
var appConstants = require('../constants/appConstants');
var appActionCreator = {
create: function(text) {
dispatcher.dispatch({
actionType: appConstants.CREATE,
text: text
});
}
};
module.exports = appActionCreator;
Store
Store中,我們需要向dispatcher注冊並處理dispatcher分發過來的action,提供接口使得view可以偵聽數據變化,查詢數據。
script/stores/appStore.js
"use strict"
var dispatcher = require('../dispatcher/dispatcher');
var EventEmitter = require('events').EventEmitter;
var appConstants = require('../constants/appConstants');
var assign = require('object-assign');
var CHANGE_EVENT = 'change';
var textList = [];
var appStore = assign({}, EventEmitter.prototype, {
create: function(text){
textList.push(text);
},
getAll: function() {
return textList;
},
emitChange: function() {
this.emit(CHANGE_EVENT);
},
addChangeListener: function(callback) {
this.on(CHANGE_EVENT, callback);
},
removeChangeListener: function(callback) {
this.removeListener(CHANGE_EVENT, callback);
}
});
dispatcher.register(function(action) {
switch(action.actionType) {
case appConstants.CREATE:
appStore.create(action.text);
appStore.emitChange();
break;
default:
}
});
Views
在view中,我們偵聽store的數據變化,在用戶交互時,發出action。
"use strict"
var React = require('react');
require('../../style/main.css');
var appActionCreator = require('../actions/appActionCreator');
var appStore = require('../stores/appStore');
var App = React.createClass({
componentDidMount: function(){
appStore.addChangeListener(this._onChange);
},
componentWillUnmount: function(){
appStore.removeChangeListener(this._onChange);
},
_onChange: function(){
var arr = appStore.getAll();
this.setState({'infoList': arr});
},
getInitialState:function(){
var arr = appStore.getAll();
return({'infoList': arr});
},
add: function(){
appActionCreator.create(React.findDOMNode(this.refs.textArea).value);
},
render: function(){
var textList = this.state.infoList.map(function(item){
return <p>{item}</p>;
});
return(
<div className="container">
<input ref="textArea" type="text"></input>
<button className="button" onClick={this.add}>add</button>
{textList}
</div>
);
}
});
module.exports = App;
entry.js
var React = require('react');
var App = require('./script/components/app');
React.render(<App />, document.body);
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script src="bundle.js"></script>
</body>
</html>
效果:
dispatcher還可以管理sotre之間的依賴, 借助react,我們還可以開發很多易維護的前端組件。
本文是一個完整的flux應用的例子,側重的是代碼,flux的理念請看博主的其它文章 😃