當下前端流行的框架,都是用狀態來描述界面(state => view),能夠說前端開發實際上就是在維護各類狀態(state),這已經成爲目前前端開發的共識。javascript
View = ViewModel(Model);
複製代碼
理想狀況下,ViewModel 是純函數,給定相同的 Model,產出相同的 View。前端
state => view 很好理解,但如何在 view 中合理地修改 state 也是一個問題。vue
圖書館的管理,原來是開放式的,全部人能夠隨意進出書庫借書還書,若是人數很少,這種方式能夠減小流程,增長效率,一旦人數變多就勢必形成混亂。java
Flux 就像是給這個圖書館加上了一個管理員,全部借書還書的行爲都須要委託管理員去作,管理員會規範對書庫的操做行爲,也會記錄每一個人的操做,減小混亂的現象。react
咱們寄一件東西的過程git
沒有快遞時:github
有了快遞公司:vuex
多了快遞公司,讓快遞公司給咱們送快遞。數據庫
當咱們只寄送物品給一個朋友,次數較少,物品又較少的時候,咱們直接去朋友家就挺好的。但當咱們要頻繁寄送給不少朋友不少商品的時候,問題就複雜了。編程
軟件工程的本質便是管理複雜度。使用狀態管理類框架會有必定的學習成本並且一般會把簡單的事情作複雜,但若是咱們想作複雜一點的事情(同時寄不少物品到多個不一樣地址),對咱們來講,快遞會讓複雜的事情變的簡單。
這同時也解釋了,是否須要添加狀態管理框架,咱們能夠根據本身的業務實際狀況和技術團隊的偏好而添加,有些狀況下,建立一個全局對象就能解決不少問題。
Redux store 是單一數據源。Redux 沒有 dispatcher 的概念,轉而使用純函數(pure function)代替。
Redux store 是不可變的(Immutable)。
和 Redux 對單向數據流的嚴格規範不一樣,Mobx 只專一於從 store 到 view 的過程。在 Redux 中,數據的變動須要監聽,而 Mobx 的數據依賴是基於運行時的,這點和 Vuex 更爲接近。
Facebook 提出了 Flux 架構思想,規範了數據在應用中的流動方式。其基本架構以下入所示,其核心理念是單向數據流,它完善了 React 對應用狀態的管理。
上圖描述了頁面的啓動和運行原理:
1.經過 dispatcher 派發 action,並利用 store 中的 action 處理邏輯更新狀態和 view
2.而 view 也能夠觸發新的 action,從而進入新的步驟 1
其中的 action 是用於描述動做的簡單對象,一般經過用戶對 view 的操做產生,包括動做類型和動做所攜帶的所需參數,好比描述刪除列表項的 action:
{
type: types.DELETE_ITEM,
id: id
};
複製代碼
而 dispatcher 用於對 action 進行分發,分發的目標就是註冊在 store 裏的事件處理函數:
dispatcher.register(function(action) {
switch (action.type) {
case "DELETE_ITEM":
sotre.deleteItem(action.id); //更新狀態
store.emitItemDeleted(); //通知視圖更新
break;
default:
// no op
}
});
複製代碼
store 包含了應用的全部狀態和邏輯,它有點像傳統的 MVC 模型中的 model 層,但又與之有明顯的區別,store 包括的是一個應用特定功能的所有狀態和邏輯,它表明了應用的整個邏輯層;而不是像 Model 同樣包含的是數據庫中的一些記錄和與之對應的邏輯。
參考連接:flux
原生 Redux API 最簡單的用例
function counter(state, action) {
if (typeof state === "undefined") {
return 0;
}
switch (action.type) {
case "INCREMENT":
return state + 1;
case "DECREMENT":
return state - 1;
default:
return state;
}
}
var store = Redux.createStore(counter); //
var valueEl = document.getElementById("value");
function render() {
valueEl.innerHTML = store.getState().toString();
}
render();
store.subscribe(render);
document.getElementById("increment").addEventListener("click", function() {
store.dispatch({ type: "INCREMENT" });
});
document.getElementById("decrement").addEventListener("click", function() {
store.dispatch({ type: "DECREMENT" });
});
document.getElementById("incrementIfOdd").addEventListener("click", function() {
if (store.getState() % 2 !== 0) {
store.dispatch({ type: "INCREMENT" });
}
});
document.getElementById("incrementAsync").addEventListener("click", function() {
setTimeout(function() {
store.dispatch({ type: "INCREMENT" });
}, 1000);
});
複製代碼
應用中全部的 state 都以一個對象樹的形式儲存在一個單一的 store 中。 改變 state 的惟一辦法是觸發 action,一個描述發生什麼的對象。 爲了描述 action 如何改變 state 樹,你須要編寫 reducers。
單一數據源
整個應用的 state
被儲存在一棵 object tree 中,而且這個 object tree 只存在於惟一一個 store
中。
state 是隻讀的
惟一改變 state 的方法就是觸發 action,action 是一個用於描述已發生事件的普通對象。
使用純函數來執行修改
爲了描述 action 如何改變 state tree ,你須要編寫 reducers
。 改變 state
的唯一方法是 dispatch action
。你也能夠 subscribe
監聽 state
的變化,而後更新 UI。
嚴格的單向數據流是 Redux 架構的設計核心。
Redux 的 API 很是少。
Redux 定義了一系列的約定(contract)來讓你來實現(例如 reducers),同時提供少許輔助函數來把這些約定整合到一塊兒。
Redux 只關心如何管理 state。在實際的項目中,你還須要使用 UI 綁定庫如 react-redux。
在寫 redux 的 action 的時候,老是須要用到擴展語句或者 Object.assign()
的方式來獲得一個新的 state,這一點對於 JavaScript 而言是對象的淺拷貝,它對內存的開銷確定是大於 mobX 中那樣直接操做對象屬性的方式大得多。
參考連接:redux-immutable seamless-immutable reselect 爲何使用 Redux 管理狀態是可預測的
redux 是 react 技術棧中的狀態控制流框架,使用了標準的函數式思想,指望(強制)全部狀態管理都是純函數。這也意味着各狀態之間都是獨立的。可是有一類狀態 redux 直接甩給了的第三方模塊,反作用模塊 redux-saga
也就成了不辭辛苦的典型表明。反作用正是由於不肯定性和可變性而得名,而其給出的狀態又是相互影響,如何解耦使得本來複雜的非線性呈現爲線性邏輯,正是有限狀態機的用武之處。
dva 首先是一個基於 redux
和 redux-saga
的數據流方案,而後爲了簡化開發體驗,dva 還額外內置了 react-router
和 fetch
,因此也能夠理解爲一個輕量級的應用框架。
在 redux 的生態圈內,每一個環節有多種方案,好比 Data 能夠是 immutable 或者 plain object,在你選了 immutable 以後,用 immutable.js 仍是 seamless-immutable,以及是否用 redux-immutable 來輔助數據修改,都須要選擇。
MobX 是一個用法簡單優雅、同時具備可擴展性的狀態管理庫。
import { observable, autorun } from "mobx";
const appState = observable({
counter: 0,
add(value) {
this.counter += value;
}
});
autorun(() => console.log(appState.counter));
setInterval(() => appState.add(1), 1000);
複製代碼
在 mobx 中咱們能夠直接修改狀態
import { observable } from "mobx";
const appState = observable({ counter: 0 });
appState.counter += 1;
複製代碼
能夠經過引入 Strict 模式來避免這種不良好的實踐:
import { useStrict } from "mobx";
useStrict(true);
複製代碼
MobX 脫胎於響應式編程(Reactive Programming),其核心思想爲 Anything that can be derived from the application state, should be derived. Automatically,即避免任何的重複狀態。
MobX 中核心的概念便是 Observable,相信接觸過響應式編程的確定很是熟悉,從後端的典型表明 RxJava 到 Android/iOS 開發中的各類響應式框架都各領風騷。
Redux / MobX 均爲客戶端開源狀態管理庫,用狀態來描述 UI 界面,它們與 React 都不具備強綁定關係,你也能夠配合別的框架來使用它們。 固然,與 React 是再合適不過的了,React 做爲 View 層的框架,經過 Virtual DOM 機制來優化 UI 渲染,Redux / MobX 則提供了將相應狀態同步到 React 的機制。
Redux 與 MobX 的不一樣主要集中於如下幾點:
shouldComponentUpdate
優化。而 MobX 只自動更新你所關心的,沒必要擔憂嵌套帶來的重渲染問題。Mobx 最關鍵的函數在於 autoRun,autoRun 的專業名詞叫作依賴收集,也就是經過天然的使用,來收集依賴,當變量改變時,根據收集的依賴來判斷是否須要更新。Mobx 使用了 Object.defineProperty
攔截 getter 和 setter,和 Vue 同樣。
Vuex 是專門爲 Vue.js 設計的狀態管理庫。把組件的共享狀態抽取出來,以一個全局單例模式管理。它採用集中式存儲管理應用的全部組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。
Vuex 的用法很簡單, 一句話總結:commit mutation,dispatch action
參考連接:Vuex 官方文檔
有限狀態機(finite-state machine)又稱有限狀態自動機,簡稱狀態機,是表示有限個狀態以及在這些狀態之間的轉移和動做等行爲的數學模型,很是有用,能夠模擬世界上大部分事物。
有限狀態機並非一個複雜的概念,簡單說,它有三個特徵:
使用狀態去影響視圖,而 Action 主要負責完成狀態間的變動。代碼如何更好的構建其核心在於使用最合理的狀態去管理界面,並用最合理的動做去實現狀態間的變動。
所謂的狀態管理,實際上就是使用有限狀態機來管理前端狀態。
有限狀態機對 JavaScript 的意義在於,不少對象能夠寫成有限狀態機。
寫代碼以前,思考一下:
而後跟着思路,完成數據與 UI 部分。
參考連接:javascript-state-machine xstate managing-state-in-javascript-with-state-machines-stent