Vuex 基礎篇
簡單講述vuex基本概念和用法
Vuex全景圖
索引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開頭的輔助函數
- 組件內可以透過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
- 組件內可以透過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
- 組件內可以透過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
- 組件內可以透過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統一管理。
基本用法
實際使用
- 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…都為全域註冊),非常好用