有關狀態管理這個詞兒已經出現好幾年了。不過實際中大多數項目其實還用不上狀態管理,並且即便在項目中用上,但也用得並很差,尤爲是初學者,更多的是去記錄各類API的用法,殊不知其核心思想,很難快速實現狀態管理的最佳實踐。javascript
以前在 Vue組件通訊事件總結 這篇文章裏研究過Vue裏面各個組件之間的數據通訊,通常頁面不是特別複雜的項目,使用這篇文章總結的通訊方式足夠了,但當前端頁面複雜度愈來愈高,props
、$emit
、$listeners
、ref / refs
、eventBus
這些方法也許還不夠方便,這個時候能夠開始嘗試vuex的狀態管理機制了。前端
用一個通俗易懂的概念來解釋狀態管理:全局變量。vue
可是在項目的開發中,咱們應該都記得前輩的叮囑:儘可能不要或少用全局變量,由於那是不可控的操做,任意的操做均可能致使數據的改變,形成全局污染,沒法追蹤數據變化過程,因此開發中咱們小菜鳥也大都避免去過多的操做全局變量。java
但當項目複雜度比較高時,也許多個組件、多個頁面之間須要實現一種數據或狀態的共享,這時候,咱們就能夠將這些狀態統一的進行管理,既能夠實現共享狀態,又能追蹤到數據的變化,可能這也是狀態管理誕生的一種緣由吧。vuex
固然,跟全局變量同樣,各個文章裏面也是叮而囑之,若是沒有哦必要,儘可能不要使用狀態管理。編程
關於如何在UI試圖中合理地修改state,Facebook提出了flux思想。redux
Flux 是一種架構思想,專門解決軟件的結構問題。後來的rudux和vux也都是由Flux的思想演化出來的。數據結構
Flux將一個應用分紅四個部分: View(視圖)、Action(動做)、Dispatcher(派發)、Store(數據)架構
總體流程:框架
這是一個單向流動的過程,
用戶訪問view -> 觸發事件action -> Dispatcher知道後告知store要更新 -> store更新,觸發視圖View更新頁面
特色:
redux的核心概念:
Redux store 是單一數據源,且store是不可變的,Redux 沒有 dispatcher 的概念,
特色:
store.dispatch()
是 View 發出 Action 的惟一途徑Store 中提供了幾個管理 state
的 API:
store.getState()
:獲取當前 statestore.dispatch(action)
:觸發 state
改變(惟一途徑)store.subscribe(listener)
:設置 state
變化的監聽函數(若把視圖更新函數做爲 listener 傳入,則可觸發視圖自動渲染)總體流程:
Action Creator -> 觸發action -> store.dispatch(action) -> reducer(state, action) -> 更新state
MobX 是經過透明的函數響應式編程使得狀態管理變得簡單和可擴展,是一個用法簡單優雅、同時具備可擴展性的狀態管理庫。
和 Redux 對單向數據流的嚴格規範不一樣,Mobx 只專一於從 store 到 view 的過程。在 Redux 中,數據的變動須要監聽,而 Mobx 的數據依賴是基於運行時的,這點和 Vuex 更爲接近。
若是你們使用過 Vue 的話相信對其雙向綁定 MVVM 的思想並不陌生,React + Mobx 至關因而 Vue 全局做用域下的雙向綁定,而 Vue 的狀態管理框架 Vuex 倒是借鑑了 Flux 架構,連尤大都說,彷佛有點你中有我,我中有你的關係。
特色:
仍然放一張vuex的示意圖:
vuex的運做原理跟redux稍有不一樣。由於Vue雖然是單向數據流,但Vue 基於 ES5 中的 getter/setter 來實現視圖和數據的雙向綁定,所以 Vuex 中 state 的變動能夠經過 setter 通知到視圖中對應的指令來實現視圖更新。且state不是經過actions來修改的,而是經過mutations。
特色:
單向數據流, 經過 store.dispatch()
調用 Action ,在 Action 執行完異步操做以後經過 store.commit()
調用 Mutation 更新 State
單一數據源
actions 能夠是 異步操做,故可在action中調用後臺接口獲取新的數據;
mutations 只能是 同步操做;
mutations 和 actions 均可直接更改 state,可是當 action 含有異步操做時,會使得數據變化混亂,難以跟蹤,使得調試困難;基於以上緣由,Vuex 規定只能是 mutations 來改變 state。
總體流程:
用戶訪問view -> 觸發事件action ->action中觸發對應的mutation -> 在mutation函數中改變state -> 經過 getter/setter 實現的雙向綁定的機制,視圖View會自動更新頁面
使用一句話總結:commit mutation,dispatch action
從上面幾種熱門的狀態管理實現方式來看,能夠發現,這幾種數據流模型幾乎都是從 action 到 view 之間的一種數據流動,總的過程能夠大體簡化爲:
action -> 更新 state(視圖層)
一、 數據狀態中心: state和store
能夠發現,在redux和flux中,數據狀態用store表示,而在vuex和mobx中,這個store被state替代。
和 Redux 中使用不可變數據來表示 state 不一樣,Vuex 中沒有 reducer 來生成全新的 state 來替換舊的 state,Vuex 中的 state 是能夠被修改的。
Vuex 中的 state 是可修改的,而修改 state 的方式不是經過 actions,而是經過 mutations。更改 Vuex 的 store 中的狀態的惟一方法是提交 mutation。
二、 行爲action
咱們想要更新視圖內容,第一步就是要有觸發的動做,action就是向store發起更新請求的最小單元。但action並不是是一個動詞,它是一個行爲的描述,本質上是一個純聲明式的數據結構,僅提供對事件的描述,不提供事件的具體邏輯
在rudux中,生成action有兩種方式:
聲明對象:
const action = {
type: 'ADD_TODO',
text: '生成一個action'
}
dispatch(action)
複製代碼
函數生成:
function addTodo(text) {
return {
type: ADD_TODO,
text
}
}
dispatch(addTodo())
複製代碼
三、dispatch
在各種應用狀態管理的模型中,一般都會有一個dispatch
方法,它就聲明在Store
上,負責調用各個Action
,而後由Store
上對應的分發機制進行處理。
四、Reducer / Mutation
如今到了咱們的第三步,更新狀態。flux和mobx對狀態更新的處理是直接更改,而redux和vuex中間還會多出一個reducer和mutation來處理更新的工做。
至於reducer和mutation,分別是針對redux和vuex的不一樣工做機制。
先看reducer,Actions
只能描述發生了什麼,並不能描述狀態發生了什麼變化,Reducers
指定 state tree
將要發生什麼,它主要的工做內容是:接受一個action,而後經過switch匹配action的type,做出相應的處理後,返回一個新的對象。爲何是新的對象呢?由於redux最核心的一個概念,store是不可變的, Redux 是一個實踐函數式編程(FP)理念的庫。下面是一個最簡單的reducer:
const items = (state = [], action) => {
switch (action.type) {
case "ADD_ITEM":
return [...state, { text: action.text }]
default:
return state
}
}
複製代碼
再來看mutation,一個 mutation 是由一個 type 和與其對應的 handler 構成的,type 是一個字符串類型用以做爲 key 去識別具體的某個 mutation,handler 則是對 state 實際進行變動的函數。
// store
const store = {
books: []
}
// mutations
const mutations = {
[ADD_BOOKS](state, book) {
state.books.push(book)
}
}
複製代碼