Flux是facebook提出的一種處理前端數據的架構,學習Flux就是學習它的思想。html
這個筆記是我在學習了阮一峯老師的Flux 架構入門教程以後得出,
裏面的例子和部分原文來自於其,不一樣在於我用es6將其改寫了,並加入了註釋。前端
作了兩三個前端外包項目,都是後端提供數據接口,邏輯主要由前端完成,深感前端邏輯之複雜,
特別是最近的一個項目,到後期業務邏輯代碼混在一塊兒根本沒法維護。因而痛定思痛,想下定決心研究下前端架構方案,
而Flux則是如今最火,最受好評的前端架構方案。react
本例代碼倉庫:flux_learn,喜歡的話給個star哦!git
咱們按Flux數據流的順序來分析,es6
View發起Action->Action傳遞到Dispatcher->Dispatcher將通知Store->Store的狀態改變通知View進行改變github
View由React組件構成,首先是MyButton.js後端
import React, {Component} from 'react' class MyButton extends Component { render() { let items = this.props.items; return ( <div> <ul> {items.map((result, key) => { return ( <div key={key}>{result}</div> ) })} </ul> <button onClick={this.props.onClick}>New Item</button> </div> ) } } export default MyButton
額,這個組件貌似沒啥好講的,會React和es6的一下就能看懂。。。架構
接下來是由對MyButton進行封裝的MyButtonController.jsapp
import React, {Component} from 'react' import MyButton from 'app/components/MyButton' import listStore from 'app/stores/listStore' import ButtonActions from 'app/actions/ButtonActions' //對Action發生器進行初始化,buttonActions能發出不一樣類型action給Dispatcher let buttonActions = new ButtonActions() class MyButtonController extends Component { constructor(props) { //把props做爲參數傳遞到super(),這樣在constructor裏便可訪問this.props屬性 super(props) this.state = { items: [] } } componentDidMount() { //在組件掛載後綁定組件的私有方法_onChange到Store,以後listStore狀態變化便可通知組件調用_onChange方法進行改變 listStore.addChangeListener(this._onChange.bind(this)) } componentWillUnmount() { //在組件移除後解除綁定組件的私有方法_onChange到Store listStore.removeChangeListener(this._onChange.bind(this)) } //組件響應Store變化的回調函數 _onChange() { this.setState({ items: listStore.getAll() }) } render() { return ( <MyButton items={this.state.items} onClick={this.createNewItem} /> ) } createNewItem() { //調用Action發生器發出增長Item的Action buttonActions.addNewItem('new item') } } export default MyButtonController
在咱們點擊新增按鈕後調用createNewItem方法發出一個'ADD_NEW_ITEM'的Action到Dispatcher函數
接下來咱們看看ButtonActions.js
import AppDispatcher from 'app/dispatcher/AppDispatcher' class ButtonActions { //發送ADD_NEW_ITEM的Action的方法 addNewItem(text) { //調用Dispatcher獲取actionType爲ADD_NEW_ITEM的Action AppDispatcher.dispatch({ actionType: 'ADD_NEW_ITEM', text: text }) } } export default ButtonActions
這裏的addNewItem方法發起了一個actionType爲ADD_NEW_ITEM的Action到Dispatcher
而後咱們再看AppDispatcher.js
import flux from 'flux' import listStore from 'app/stores/listStore' //拿到flux模塊裏的Dispatcher類 let Dispatcher = flux.Dispatcher; //用Dispatcher類new一個AppDispatcher對象 let AppDispatcher = new Dispatcher(); //調用register方法註冊接收到各類actionType的Action以後的回調函數 AppDispatcher.register(function (action) { switch (action.actionType) { case 'ADD_NEW_ITEM': listStore.addNewItemHandler(action.text) listStore.emitChange() break; default: } }) export default AppDispatcher
最後是ListStore.js
import EventEmitter from 'events' class ListStore extends EventEmitter { constructor() { super() //初始化數據 this.items = [] } //返回全部數據的方法 getAll() { return this.items } //增長數據的處理函數 addNewItemHandler(text) { this.items.push(text) } //提交變化 emitChange() { this.emit('change') } //監聽函數,當有變化時調用註冊的回調方法 addChangeListener(callback) { this.on('change', callback) } //remore監聽函數 removeChangeListener(callback) { this.removeListener('change', callback) } } //new一個listStore做爲單例暴露給其它模塊使用 let listStore = new ListStore() export default listStore
它負責記錄數據和狀態並在有變化時改變View