Vuex,從入門到入門

Vuex 是什麼?

官方是這麼說的:Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式。它採用集中式存儲管理應用的所有組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。

不懂?呵呵,沒關係。我是這麼認爲的:Vuex 就是前端爲了方便數據的操作而建立的一個” 前端數據庫“。且聽下文分解。。。

模塊間是不共享作用域的,那麼B 模塊想要拿到 A 模塊的數據,我們會怎麼做?不要去想什麼”狀態管理“、”vuex“、”redux“、”函數式編程“什麼的。。。

我們會定義一個全局變量,叫
aaa 吧,就是
window.aaa。然後把A 模塊要共享的數據作爲屬性掛到 B 模塊上。這樣我們在 B 模塊中通過
window.aaa 就可以拿到這個數據了。

但是問題來了,B 模塊拿到了共享的數據,就叫他
xxx 吧?得了,名字太混亂了,咱先給它們都改下名字。那個全局變量既然是存東西的,就叫
store 吧,共享的數據就叫
state 吧,你叫他
data 也一樣,反正我是叫它
state 了。

繼續說我們的問題,問題是什麼呢?B 模塊拿到了 A 模塊的數據
state,但是這個數據不是一成不變的呀,A 要操作這個數據的。那麼我們是不是要在這個數據——state 改變的時候通知一下 B?那寫個自定義事件吧。。。

好吧,你自己已經實現了一個迷你版的
vuex,其實
vuex 就幫你做了這點事兒。我們來看下它裏面都有什麼玩意兒。

這就是一個典型的
使用vuex生成的倉庫。不懂?呵呵,沒關係,也沒打算說它。我們聊點別的。

後端是幹什麼的?進行數據庫操作,處理請求,根據請求分發響應。我們就聊聊數據庫的操作,不說 API。首先,你得能取吧?那麼得有一套取數據的 API,我們給他們集中起個名字吧?既然是獲取,那就叫getter 吧。我們還得存數據呀,是吧。存數據就是對數據庫的修改,這些 API,我們也得給它起個名字,就叫
mutation,就這麼定了。

OK,vuex 生成的倉庫也就這麼出來了,所以我說 vuex 就是” 前端的數據庫“。State 就是數據庫。Mutations 就是我們把數據存入數據庫的 API,用來修改
state 的。getters 是我們從數據庫裏取數據的 API,既然是取,那麼你肯定不能把數據庫給改了吧?所以
getters 得是一個”純函數“,就是不會對原數據造成影響的函數,比如
數組的concat()方法、slice()方法;與之對應的是數組的
push()方法、splice()方法,他們會改變原數組的值。然後我們把這幾部分用
store 包一下,” vuex “就搗置出來了,用數據了就從
state 中取,改數據了記得
mutation 到 state 中。

哎,還漏了個
actions 呢。你想呀,後端從前端拿到了數據,總要做個處理吧,處理完了再存到數據庫中。其實這就是
action的過程。當然你也可以不做處理,直接丟到數據庫,所以vuex也可以在
action 中直接存,就是直接mutation。

現在,我們再來看看 vuex 的數據流。後(qian)端通過
action處理數據,然後通過
mutation 把處理後的數據放入數據庫(state)中,誰要用就通過
getter從數據庫(state)中取。

你都理解了?好吧,有卵用,還得迴歸到 API 上。

1、getters

// 獲取控制變量 ctrl
export function getShowPage (state) {
  return state.ctrl.showPage
}

getters 是一個純函數,接收參數 state,返回你想取的值,都不需要貼數據結構,很清晰吧。

// 獲取store各項信息
export function getMeta (state) {
  return state.meta
}

這張圖上,我們返回的是一個被變量控制的值,還可以先對獲得的數據進行處理,然後再返回出去。

2、mutations

// 公共控制變量 ctrl
  [SHOW_PAGE] (state) {
    state.ctrl.showPage = true
  },

一個最簡單的
mutation,就是把
state.ctrl.showData 的值改成 true,好吧,我覺得我是在說廢話。Mutation除了接收
state 作爲第一個參數外,還可以接收其他的參數,比如:

 [NEW_DATA] (state, payload, id){
    const newData = {id, data: payload}
    state.meta = Object.assign({}, {currentData: id})
    state.datas = Object.assign({}, newData)
  },

不用說了吧。。。

3、store與state

state就是根據你項目的需求,自己定義一個數據結構。Store中至少要注入兩項,state 和 mutation。

const state = {
  currentPage: 1,
  user: '0121213',
  change: 0,
  page,
  ctrl,
  meta,
  configs,
  datas
}

export default new Vuex.Store({
  state,
  mutations,
})

這是我定義的
state 和 store 的注入。

4、action

先來一個簡單點的。

export const updateName = function({ dispatch, state }, name) {
  const payload = {name}
  dispatch('UPDATE_PAGE', payload)
}

一個叫
updateName 的 action(數據的中間處理),前面花括號是一個參數,state,如果不理解,看看阮一峯的 ES6入門,對象解構。它接收用戶輸入的數據
name,然後中間處理的過程就是把
name 包成了對象{name: name},然後通過
mutation(update_page)
存儲。至於 update_page 幹了什麼,那不是
action(中間處理)的事兒,那是
mutation(存儲)的邏輯。

export const updateData = function({ dispatch, state }, data) {
  const payload = data
  const id = state.meta.currentData
  if (id === 'initial') {
    const id = createDataId()
    dispatch('NEW_DATA', payload, id)
  } else {
    dispatch('UPDATE_DATA', payload)
  }
}

這個 action 叫 updateData,裏面先把 data 改了個名字,然後加了判斷,如果 id 是‘initial’
就怎麼存。。。否則怎麼存。。。

再來一個:

這個 action 很長,被我收起來了,我們看看它都做了什麼。接收一個參數 payload,判斷如果 id 是 initial,就生成
id,然後怎麼存。。。如果
id 不是 initial,就怎麼存。。。好像都一個套路。接着看,定義空的” privateConfig“、”initialData“,switch 塊裏面就是生成 privateConfig、initialData的地方。然後判斷如果
cfid 是 initial,就生成
id,然後怎麼存。。。如果
cfid 不是 initial,就怎麼存。。。好吧,全是套路。

通過這幾個小例子,我希望大家可以看到的是,各個類型的 API各司其職,mutation 只管存,你給我(dispatch)我就存;action只管中間處理,處理完我就給你,你怎麼存我不管;Getter 我只管取,我不改的。

咱們再來看一個聽着玄乎其神的異步操作的 action。

export const save = function({ dispatch, state }) {
  const params = state
  api.save(params).then(function(res) {
    console.log(res)
    dispatch('SAVE_SUCCESS', res)
  }).catch((err) => {
    console.log(err)
    dispatch('SAVE_FAIL', err)
  })
}

一個叫 save 的 action。首先在裏面發起了一個請求,這個請求是經過包裝的(改了名字叫
api.save),咱不管它改名字這茬兒。第一個
then 就是成功的回調,通過
res 拿到數據,拿到數據了就怎麼存。。。第二個
catch 就是失敗的回調,通過
err 拿到錯誤信息,拿到錯誤信息了怎麼存。。。呵呵,跟if判斷差不多嘛。。。其實異步的
action 還可以發送第三個
dispatch 的,在發起請求前先保存下原始數據,有時候有需求會用到的,比如官方 DEMO 的購物車。

看來形式怎麼變,action 裏面的邏輯不會變,它做的事情不會變。

5、它們是什麼?

至於 mutation_type,mudules。。。這些都不是重點,可用可不用。Vuex 最強大的地方還在於它的伸縮性。你項目大了,需要分
mudules,項目小了一樣可以用呀,甚至只需要建立一個
store.js,你有什麼理由不用它?

理解了 getter,mutation,action了,但是也許你還不知道該怎麼去用,因爲你還不知道他們是什麼東西。

截的官網的圖,重點不是 mapGetters,重點是mapGetters寫在了哪兒。寫在了 computed
裏面,這說明雖然
getter我們寫的是函數,但是我們應該把它當成計算屬性來用。再來看
action。

action放在了 methods 裏面,說明我們應該把它當成函數來用。你以前寫的 onclick = ‘函數’,現在就可以
onclick = ‘action’。我們在 vue 裏面是這樣寫的,@click
= “action()”,加不加括號看心情。

最後來看看 mutation。

它是在 store 裏面寫的,這說明,它就是個半成品,中間量,我們不應該在外面去操作它。

Vuex 什麼時候用?

如果你問了這個問題,說明你不該用。但這個問題可以很容易並且很正確的回答。

等你痛了的時候,你就該用了。如果你連自己的代碼都看不懂的時候,如果你自己都搞不清楚值在組件中是怎麼傳遞的時候,如果你自己代碼寫了一半,噁心的想要撂挑子不幹的時候,趕緊的,Vue.use(Vuex)!


看完文章,多翻翻評論,裏面都是小朋友們在開發中遇到的問題,比文章更有價值...

轉自https://zhuanlan.zhihu.com/p/24357762

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章