Vuex 基礎篇

簡單講述vuex基本概念和用法

Juo Penguin
8 min readSep 14, 2020

Vuex全景圖

High res image: https://i.imgur.com/6a6CzZp.jpg

索引index

vuex基本架構: state, getter, actions, mutations

state(store): 全域狀態

getters: vuex的”computed”

mutations: 負責修改state / 保持sync

actions: 負責觸發任務 / async交給它

modules: 拆分vuex

Vuex基本架構

vuex的基本單位為一個store,通常會包含以下幾個元素,這邊我們先了解vuex store的架構就好,稍後會一個個講解store中的各個詳細用法。

  • state: 狀態放這邊
  • getters: 預先處理state,類似vue的computed
  • actions: 負責”commit”任務給mutations
  • mutations: 負責修改state

State 全域狀態

組件只管使用state資料就對了,並沒其他太複雜的邏輯,跟使用data/props差不多。

主要有2個方法可以取得state

其實state, getters, actions, mutations都會有兩個方法可以取得,分別是this.$store.{…} 或是map開頭的輔助函數

  1. 組件內可以透過this.$store.state取得
this.$store.state.todoList // state.todoList

2. 或是用mapState函數來做對應

// TodoItem.js
import { mapState } from 'vuex'
{
//...
computed: {
...mapState({
todoList: state => state.todoList,
//這兩者一樣,都是從state取得todoList
todoList: 'todoList',
//這兩者一樣,都是從state取得todoList

// 混合組件自己的data/props
todoCountWithClick() {
return todoList.length + this.clickCount;
}
})
},
}

Getters: vuex的”computed”

getters可以被認為是store中的computed(官方文件說的),相關數值也跟computed一樣會被暫存,直到相關state被更新。

基本用法

2個方法取得getters

  1. 組件內可以透過this.$store.state取得
this.$store.getters.doneTodoList

備註:可以透過return 一個function(curry化)來做更彈性的處理

computed: { 
doneTodosCount() {
return this.$store.getters.searchTodoList(this.value);
}
}

2. 或是用mapState函數來做對應,組件中即可直接使用

computed: { 
...mapGetters(['doneTodoList'])
}
// 或是用object形式
computed: {
...mapGetters({ myDoneTodos: 'doneTodoList', })
}

在看actions之前,我們先來看看mutations在做什麼。

vuex中可以不使用actions,因為actions可以算是一個統整mutations任務的地方,actions負責發送任務和資料給mutations執行,再由mutations做state的修改。

Mutations: 負責修改state

mutations前面也提到很多次,是負責處理state資料更新的地方。

基本用法

2個方法使用mutations

  1. 組件內可以透過this.$store.commit使用,mutation接受2種形式的「呼叫」
// 第一種params
this.$store.commit('removeTodo', payload)
// 第二種object params,有沒有發現與redux的reducers接受的actions一樣形式?
this.$store.commit({
type: 'removeTodo',
payload,
})

2. 用mapState函數來做對應,組件中即可直接使用

methods: { 
...mapMutations(['removeTodo'])
}
// 或是用object形式
methods: {
...mapMutations({ removeOneTodo: 'removeTodo', })
}

Actions: 負責提交commit給mutations

雖然我們可以直接使用mutations對state進行操作,但是如果今天加上非同步的資料取得,或是比較複雜的commit邏輯,這時候actions就派上用場了!

actions「不會」直接操作state,它只負責「派遣任務」(commit的type)和「人員調度」(commit的payload),就像是軍師一樣。

基本用法

2個方法使用actions

  1. 組件內可以透過this.$store.dispatch使用,actions和mutations一樣接受2種形式的「呼叫」
// 第一種params
this.$store.dispatch('addTodo', payload)
// 第二種object params
this.$store.dispatch({
type: 'addTodo',
payload,
})

2. 用mapState函數來做對應,組件中即可直接使用

methods: { 
...mapActions(['addTodo'])
}
// 或是用object形式
methods: {
...mapActions({ addOneTodo: 'addTodo', })
}

備註: actions本身如果為async function,其他的action也要做相對應的async處理

Modules

當專案的規模越來越大,做的是類似SPA(Single Page Application時)的網頁APP,state, actions…等也越來越複雜,我們會需要管理更多的內部狀態,這時可以將store拆成好幾個「modules」,由store統一管理。

基本用法

實際使用

  1. module內部可以透過rootState, rootGetters取得store底下其他modules的state, getters

2. 命名空間(namespace)

如果沒有啟用在各個module中啟用namespaces(預設是false),那麼actions, mutations…等會被註冊在全域的命名。

但我們如果要更好地管理各module,而且又怕命名有重複(像是add, remove這種常用的),那麼可以設定namespaces: true,你的modules會根據module名自動註冊一個"路徑",路徑類似router的概念,用這個路徑來取得該指定層級的getters, actions…

3. map輔助函數及”路徑"的簡寫: mapState和mapActions…等,如果在使用命名空間的情況下,可以透過"先給定路徑"的方式來取得module底層的state, actions…

// 以下是已經使用namespace的情況//原本
mapState({
myTodoList: state => state.todo.todoList,
myTodoStatus: state => state.todo.status
})
// 可以改為這樣
mapState('todo', {
myTodoList: state => state.todoList,
myTodoStatus: state => state.status
})

總結

  • state: 作為vuex的全域狀態;
  • getters: 負責先處理好state資料;
  • mutations: 負責修改state;
  • actions負責commit任務給mutations,或是再dispatch任務給其他任務;
  • modules: 拆分store為各個"module",啟用namespace可以將各module自動命名註冊(否則所有的actions, mutations…都為全域註冊),非常好用

下一篇會講解關於vuex的實戰應用,會採用官網的範例加上自己的重構,作為進階篇的範例解說。

--

--

Juo Penguin
Juo Penguin

Written by Juo Penguin

不挑食的雜食者,近期的目標是瘦10公斤。

No responses yet