原文連接:The Flux Quick Start Guidejavascript
本文將歸納性的介紹如何使用 Flux 架構開發 JavaScript 應用,用盡量少的篇幅帶你熟悉 Flux 的核心概念。你也能夠結合 starter kit 一塊兒學習。你最好先對 React 有基本的瞭解,而且有一些開發 React 組件的經驗。若是不熟悉也不要緊,能夠先讀一讀這篇文章 The React Quick Start Guide (譯註:中文版本 React 入門)。html
Flux 是用來構建用戶端 Web 應用的架構,它包含三個核心概念:Views, Stores 和 Dispatcher,還有一些次級概念:Actions, Action Types, Action Creators 和 Web Utils。java
請耐心學習如下概念定義而後再看後面的教程。當你準備開始開發 Flux 應用以前,建議你再回過頭來看一遍基本概念。react
Views 即 React 組件。它們負責渲染界面,捕獲用戶事件,從 Stores 獲取數據。git
Stores 用於管理數據。 一個 Store 管理一個區域的數據,當數據變化時它負責通知 Views。github
Dispatcher 接收新數據而後傳遞給 Stores,Stores 更新數據並通知 Views。segmentfault
Actions 是傳遞給 Dispatcher 的對象,包含新數據和 Action Type。服務器
Action Types 指定了能夠建立哪些 Actions,Stores 只會更新特定 Action Type 的 Actions 觸發的數據。架構
Action Creators 是 Actions 的建立者,並將其傳遞給 Dispatcher 或 Web Utils。app
Web Utils 是用於與外部 API's 通訊的對象。例如 Actions Creator 可能須要從服務器請求數據。
是否是一次給的信息量太多啦?強烈建議大家結合 starter kit 邊看文章邊敲代碼,能夠達到更好的學習效果。
提示:這裏省略了 constants 和 Web Utils,是爲了更快速簡單地理解 Flux。更深刻閱讀 官方示例 能很好地補充這些知識。
部署好 starter kit 後,你會看到在 src
目錄下有個 app.js
文件。
var React = require('react'); var Comments = require('./views/comments'); var CommentForm = require('./views/comment-form'); var App = React.createClass({ render: function() { return ( <div> <Comments /> <CommentForm /> </div> ); } }); React.render(<App />, document.getElementById('app'));
上面代碼把 Views 渲染到 DOM 中。先忽略 Comments
,看一下 CommentFrom
的實現。
var React = require('react'); var CommentActionCreators = require('../actions/comment-action-creators'); var CommentForm = React.creatClass({ onSubmit: function(e) { var textNode = this.refs.text.getDOMNode(); var text = textNode.value; textNode.value = ''; CommentActionCreators.createComment({ text: text }); }, render: function() { return ( <div className='comment-form'> <textarea ref='text' /> <button onClick={this.onSubmit}>Submit</button> </div> ); } }); module.exports = CommentForm;
CommentForm
依賴的 CommentActionCreators
是一個 Action Creator (正如它的名字同樣)。
當表單提交時 createComment
函數傳遞了 comment
對象,它的值是根據 textarea 的值構造出來的。讓咱們開發這個 Action Creator 來接收 comment。
在 actions
目錄裏有以下的 comment-action-creators.js
文件。
var AppDispatcher = require('../dispatcher/app-dispatcher'); module.exports = { createComment: function(comment) { var action= { actionType: "CREATE_COMMENT", comment: comment }; AppDispatcher.dispatch(action); } };
createComment
函數構造了一個 Action,包含 Action Type 和 comment 數據,並將這個 Action 傳遞給 Dispatcher 的 dispatch
函數。
接下來編寫 Dispatcher 用於接收 Actions。
提示:也能夠把這些邏輯寫在 View 裏面 - 直接跟 Dispatcher 通訊,但最佳實踐是用 Action Creator。它能下降代碼的耦合度並給 Dispatcher 提供一個單獨的接口。
在 dispatcher
目錄下有一個 app-dispatcher.js
文件。
var Dispatcher = require('flux').Dispatcher; module.exports = new Dispatcher();
Flux 庫的 Dispatcher 提供了一個 dispatch
函數,將接收到的 Actions 傳遞給全部註冊的回調函數,回調函數由 Stores 提供。
提示:這裏沒有 Dispatcher 的具體實現,源碼在這裏。
在 stores
目錄下有一個 comment-store.js
文件。
var AppDispatcher = require('../dispatcher/app-dispatcher'); var EventEmitter = require('events').EventEmitter; var assign = require('object-assign'); var comments = []; var CommentStore = assign({}, EventEmitter.prototype, { emitChange: function() { this.emit('change'); }, addChangeListener: function(callback) { this.on('change', callback); }, removeChangeListener: function(callback) { this.removeListener('change', callback); }, getAll: function() { return comments; } }); AppDispatcher.register(function(action) { switch(action.actionType) { case "CREAT_COMMENT": comments.push(action.comment); CommentStore.emitChange(); break; default: } }); module.exports = CommentStore;
這段代碼分爲兩部分:建立 Store 和 註冊 Store。
Store 由 EventEmitter.prototype
和自定義對象整合而成。EventEmitter.prototype
給 Store 賦予了訂閱和觸發事件的能力。
自定義對象定義了訂閱和取消訂閱事件的函數,同時定義了 getAll
函數返回 comments
數據。
而後,經過 Dispatcher 註冊了一個回調函數。當 Dispatcher 調用 dispatch
時傳遞 Actions 參數給每一個註冊過的回調函數。
如今咱們須要一個 View 來展現 Store 的數據,並訂閱數據的變化。
在 views
目錄裏有個 comments.js
文件。把它修改爲以下所示:
var React = require('react'); var CommentStore = require('../stores/comment-store'); function getStateFromStore() { return { comments: CommentStore.getAll() } } var Comments = React.createClass({ onChange: function() { this.setState(getStateFromStore()); }, getInitialState: function() { return getStateFromStore(); }, componentDidMount: function() { CommentStore.addChangeListener(this.onChange); }, componentWillUnmount: function() { CommentStore.removeChangeListener(this.onChange); }, render: function() { var comments = this.state.comments.map(function(comment, index) { return ( <div className='comment' key={'comment-' + index}> {comment.text} </div> ); }); return ( <div className='comments'> {comments} </div> ) } }); module.exports = Comments;
getStateFromStores
函數從 Store 獲取 comment 數據,並在 getInitialState
中設置爲初始值。
在 componentDidMount
中,onChange
函數做爲 addChangeListener
的回調函數,當 Store 觸發 change
事件時 onChange
函數將被調用,即當 Store 數據變化時,它用於更新組件的 state 狀態。
最後 componentWillUnmount
將 onChange
事件監遵從 Store 移除。
如今這個 Flux 應用能夠運行起來了,同時咱們也學習了 Flux 架構的核心概念:Views, Stores 和 Dispatcher。
當提交 comment 時,View 調用了 Action Creator
Action Creator 建立一個 Action 並傳給 Dispatcher
Dispatcher 將 Action 發送給 Store 中註冊的回調函數
Store 更新 comment 數據,並觸發一個 change 事件
View 更新 state 並從新渲染界面
這就是 Flux 的本質,Dispatcher 發送數據給全部 Stores,後者通知 Views 進行更新。
要想更深刻理解 Flux 架構,我建議閱讀 官方文檔,或者看看這個 視頻教程,還有 官方示例。
若是本文有什麼錯誤之處,歡迎在 twitter 上聯繫我,或者給我提 pull request。歡迎你們給我提建議改善這邊文章。