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/fluxDemocss
mkdir script && cd script mkdir actions components dispatcher stores constants cd .. touch entry.js index.html webpack.config.js
關於webpack,博主的webpack系列文章已經介紹,再此,再也不贅述。
安裝moudles(關於moudles的選型,仁者見仁,智者見智,無需拘束於如下的例子)。html
npm init npm install babel-loader css-loader style-loader flux react keymirror events obejct-assign --save
flux中, Dispatcher是單例的,因此,直接向下面代碼同樣返回一個實例。以後,Action與Store都會用到它們。前端
script/dispatcher/dispatcher.jsreact
var Dispatcher = require('flux').Dispatcher; module.exports = new Dispatcher();
實現一個枚舉,用於定義全部的Action類型,藉助於keymirror實現webpack
script/constants/appConstants.jsgit
var keyMirror = require('keymirror'); module.exports = new keyMirror({ CREATE: null });
ActionCreator要藉助dispatcher來分發action。github
script/actions/appActionCreator.jsweb
"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中,咱們須要向dispatcher註冊並處理dispatcher分發過來的action,提供接口使得view能夠偵聽數據變化,查詢數據。npm
script/stores/appStore.jsbabel
"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: } });
在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;
var React = require('react'); var App = require('./script/components/app'); React.render(<App />, document.body);
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <script src="bundle.js"></script> </body> </html>
效果:
dispatcher還能夠管理sotre之間的依賴, 藉助react,咱們還能夠開發不少易維護的前端組件。 本文是一個完整的flux應用的例子,側重的是代碼,flux的理念請看博主的其它文章 :)