我的現階段對Flux架構的理解,求拍磚求star!
原文連接:https://github.com/kuitos/kuitos.github.io/issues/27前端
React 簡介請戳 這裏react
Flux是Facebook用來構建客戶端web應用的應用架構。它利用單向數據流的方式來組合react中的視圖組件。它更像一個模式而不是一個正式的框架,開發者不須要太多的新代碼就能夠快速的上手Flux。git
事件調度中心,flux模型的中心樞紐,管理着Flux應用中的全部數據流。它本質上是Store的回調註冊。每一個Store註冊它本身並提供一個回調函數。當Dispatcher響應Action時,經過已註冊的回調函數,將Action提供的數據負載發送給應用中的全部Store。應用層級單例!!github
負責封裝應用的業務邏輯跟數據的交互。web
Store中包含應用全部的數據redux
Store是應用中惟一的數據發生變動的地方架構
Store中沒有賦值接口---全部數據變動都是由dispatcher發送到store,新的數據隨着Store觸發的change事件傳回view。Store對外只暴露getter,不容許提供setter!!禁止在任何地方直接操做Store。框架
controller-view 能夠理解成MVC模型中的controller,它通常由應用的頂層容器充當,負責從store中獲取數據並將數據傳遞到子組件中。簡單的應用通常只有一個controller-view,複雜應用中也能夠有多個。controller-view是應用中惟一能夠操做state的地方(setState())異步
view(UI組件) ui-component 職責單一隻容許調用action觸發事件,數據從由上層容器經過屬性傳遞過來。mvvm
action creators 做爲dispatcher的輔助函數,一般能夠認爲是Flux中的第四部分。ActionCreators是相對獨立的,它做爲語法上的輔助函數以action的形式使得dispatcher傳遞數據更爲便利。
view --> actionCreators
// Nav.jsx export default class Nav extends React.Component { _handleClick(nav) { NavActionCreators.clickNav(nav); } render() { let itemList = this.props.list.map((nav, index) => { return ( <li className="index-menu-item" onClick={this._handleClick.bind(this, nav)} key={index}> <span>{nav.text}</span> </li> ); }); return ( <nav className="index-menu"> <ul className="index-menu-list"> {itemList} </ul> </nav> ); } }
action dispatch
// NavActionCreators.js export default { clickNav(nav){ AppDispatcher.dispatch( { type: ActionTypes.CLICK_NAV, nav } ); } };
dispatcher --> store callback
AppDispatcher.register(action => { switch (action.type) { // nav點擊 case ActionTypes.CLICK_NAV: IndexWebAPIUtils.getGiftList(_currentUserInfo.userId, action.nav.id) .then(function (giftList) { _currentGiftList = giftList; IndexStore.emitChange(); }); break; // no default } });
store emitChange --> controller view --> setState
export default class Index extends React.Component { constructor(props) { super(props); let currentUser = UserStore.getCurrentUser(); this.state = IndexStore.getAll(); } componentDidMount() { IndexStore.addChangeListener(this._onChange.bind(this)); } componentWillUnmount() { IndexStore.removeChangeListener(this._onChange.bind(this)) } _onChange() { this.setState(IndexStore.getAll()); } render() { let state = this.state; return ( <div className="page active"> ... <Nav list={state.navList}/> ... </div> ); } }
由於angular雙向綁定的緣由,咱們永遠沒法知道數據在哪一刻處於穩定狀態,因此咱們常常會在angular中看到經過setTimeout的方式處理一些問題(其實有更優雅的解決方案,不在本次討論以內)。同時因爲雙向綁定的緣由,行爲的流向咱們也很難預測,當視圖的model變多的時候,若是再加上一堆子視圖依賴這些model,問題發生時定位簡直是噩夢啊(這也是angular的錯誤信息那麼不友好的緣由,由於框架開發者也沒法肯定當前行爲是誰觸發的啊,綁定的人太多了...)。可是這裏仍是要強調一點就是,並非說雙向綁定就必定會致使不穩定的數據狀態,在angular中咱們經過一些手段依然可使得數據變得穩定,只是雙向綁定(mvvm)相對於flux更容易引起數據不穩定的問題。
flux裏view是不容許直接修改store的,view能作的只是觸發action,而後action經過dispatcher調度最後纔會流到store。全部數據的更改都發生在store組件內部,store對外只提供get接口,set行爲都發生在內部。store裏包含全部相關的數據及業務邏輯。全部store相關數據處理邏輯都集中在一塊兒,避免業務邏輯分散下降維護成本。
view全部的數據來源只應該是從屬性中傳遞過來的,view的全部表現由上層控制視圖(controller-view)的狀態決定。咱們能夠把controller-view理解爲容器組件,這個容器組件中包含若干細小的子組件,容器組件不一樣的狀態對應不一樣的數據,子組件不能有本身的狀態。也就是,數據由store傳遞到controller-view中以後,controller-view經過setState將數據經過屬性的方式自上而下傳遞給各個子view。
因爲二、3兩條緣由,view自身須要作的事情就變得不多了。業務邏輯被store作了,狀態變動被controller-view作了,view本身須要作的只是根據交互觸發不一樣的action,僅此而已。這樣帶來的好處就是,整個view層變得很薄很純粹,徹底的只關注ui層的交互,各個view組件以前徹底是鬆耦合的,大大提升了view組件的複用性。
對單個應用而言dispatcher是單例的,最主要的是dispatcher是數據的分發中心,全部的數據都須要流經dispatcher,dispatcher管理不一樣action於store之間的關係。由於全部數據都必須在dispatcher這裏留下一筆,基於此咱們能夠作不少有趣的事情,各類debug工具、動做回滾、日誌記錄甚至權限攔截之類的都是能夠的。
flux只是一個架構模式,並非一個已實現好的框架,因此基於這個模式咱們須要寫不少樣板代碼,代碼量duang的一會兒上來了。。不過好在目前已經有不少好用的基於flux的第三方實現,目前最火的屬redux。
dispatcher做爲flux中的事件分發中心,同時還要管理全部store中的事件。當應用中事件一多起來事件時序的管理變得複雜難以維護,沒有一個統一的地方能清晰的表達出dispatcher管理了哪些store。
按flux流程,action中處理:依賴該action的組件被迫耦合進業務邏輯
按store職責在store中處理:store狀態變得不穩定,dispatcher的waitFor失效
前端摩爾定律:前端每18個月難度增長一倍
沒有銀彈