Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式 + 庫,簡單一點(diǎn)理解就是為了可以實(shí)現(xiàn)組件之間實(shí)現(xiàn)相互共享數(shù)據(jù)這需求。
以下代碼實(shí)現(xiàn)可以在CodeSandbox實(shí)現(xiàn)
一、基本用法:
import { createApp } from 'vue' //引入vue
import App from './App.vue' //APP組件
import {createStore} from 'vuex' //引入vuex
const app=createApp(App) //創(chuàng)建vue實(shí)例
app.mount('#app') //將vue實(shí)例掛載到HTML中id為app的標(biāo)簽中
const store=createStore({ //創(chuàng)建vuex的實(shí)例
state(){
return{
count:0
}
},
mutations:{
increment(state){
state.count++
}
}
})
app.use(store) //將創(chuàng)建實(shí)例store掛載到vue實(shí)例上
(1)、 直接調(diào)用如下:
store.commit('increment') //store.commit 方法觸發(fā)狀態(tài)變更
console.log(store.state.count) //store.state 來獲取狀態(tài)對(duì)象
(2)、在 Vue 的組件中調(diào)用, 可以通過 this.$store 訪問store實(shí)例。現(xiàn)在我們可以從組件的方法提交一個(gè)變更:
methods: {
add() {
this.$store.commit('increment') //store.commit 方法觸發(fā)狀態(tài)變更
console.log(this.$store.state.count) //store.state 來獲取狀態(tài)對(duì)象
}
}
二、核心概念使用
(1)、state :包含了store中存儲(chǔ)的數(shù)據(jù)各個(gè)狀態(tài)(初始化數(shù)據(jù)地方)。
const store=createStore({ //創(chuàng)建vuex的實(shí)例
state(){
return{
count:0
}
},
})
//直接調(diào)用
store.state.count//store.state 來獲取狀態(tài)對(duì)象
//在組件中調(diào)用
this.$store.state.count//this.$store.state 來獲取狀態(tài)對(duì)象
一般來說不這樣直接獲取狀態(tài)對(duì)象數(shù)據(jù),通常都是通過getter方法獲取
(2)、getter: 類似于 Vue 中的計(jì)算屬性,getters根據(jù)state或者其他getters計(jì)算出另一個(gè)變量的值,當(dāng)其依賴的數(shù)據(jù)變化時(shí)候,它也會(huì)實(shí)時(shí)更新。
getter 接受 state 作為其第一個(gè)參數(shù),也可以接受其他 getter 作為第二個(gè)參數(shù)
const store=createStore({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
doneTodos (state) {
//在getters中對(duì)state數(shù)據(jù)進(jìn)行處理,后面就可以通過getters接口間接獲取state數(shù)據(jù)
return state.todos.filter(todo => todo.done)
}
}
})
方法一:
//直接調(diào)用
console.log(store.getters.doneTodos)//store.getters 來間接獲取狀態(tài)對(duì)象
方法二:
//在組件中調(diào)用
console.log(this.$store.getters.doneTodos)//this.$store.getters 來間接獲取狀態(tài)對(duì)象
方法三:
在組件中還可以通過mapGetters 輔助函數(shù)利用computed函數(shù)間接獲取狀態(tài)對(duì)象
import { mapGetters } from 'vuex' //必須從vuex中引入mapGetters函數(shù)
export default {
// 組件其他代碼省略
computed: { // 使用對(duì)象展開運(yùn)算符將 getter 混入 computed 對(duì)象中
...mapGetters([ // ...mapGetters函數(shù)映射
'doneTodos ', //這個(gè)doneTodos 是getter定義方法
'anotherdoneTodos ', //這個(gè)anotherdoneTodos 也是getter定義方法
])
}
}
如果你想將一個(gè) getter 屬性另取一個(gè)名字,使用對(duì)象形式:
...mapGetters({
// 把 `this.doneCount` 映射為 `this.$store.getters.doneTodos `
doneCount: 'doneTodos '
})
總結(jié)mapGetters輔助函數(shù)適合用于getter定義了許多方法,在組件調(diào)用時(shí)候不想一個(gè)一個(gè)寫this.$store.getters來間接獲取狀態(tài)對(duì)象,就可以通過輔助函數(shù)全部映射過組件直接調(diào)用映射后名字即可。
(3)、mutation: 同步執(zhí)行,是改變store中狀態(tài)的執(zhí)行者,簡單一點(diǎn)就是通過提交mutation來改變state中的數(shù)據(jù)。
1、只有state一個(gè)參數(shù)
const store = createStore({
state: {
count: 1
},
mutations: {
increment (state) {
state.count++ // 變更狀態(tài)
}
}
})
2、帶載荷(payload),也就是第二參數(shù),由組件傳進(jìn)來的,多數(shù)情況下payload都是一個(gè)對(duì)象。
const store = createStore({
state: {
count: 1
},
mutations: {
increment (state,payload) {
state.count += payload.amount // 變更狀態(tài)
}
}
})
方法一:
//直接調(diào)用
store.commit('increment')//通過store.commit 觸發(fā)mutation事件
store.commit('increment', {amount: 10})//帶payload情況,觸發(fā)事件
方法二:
//在組件中調(diào)用
this.$store.commit('increment')//通過this.$store.commit 觸發(fā)mutation事件。
this.$store.commit('increment', {amount: 10})//帶payload情況,觸發(fā)事件
方法三:
在組件中還可以通過mapMutations 輔助函數(shù)通過映射利用methods方法
import { mapMutations } from 'vuex'
export default {
methods: {
...mapMutations([
'increment', // 將 `this.increment()` 映射為 `this.$store.commit('increment')`
// `mapMutations` 也支持載荷:
'incrementBy' // 將 `this.incrementBy(amount)` 映射為 `this.$store.commit('incrementBy', amount)`
]),
}
}
(4)、action: 異步方法,action并不直接改變state,而是提交觸發(fā)mutation從而改變state狀態(tài)。
const store = createStore({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
方法一:
//直接調(diào)用
store.dispatch('increment')//store.dispatch觸發(fā)mutation事件
store.dispatch('increment', {amount: 10})//帶payload情況,觸發(fā)事件
方法二:
//在組件中調(diào)用
this.$store.dispatch('increment')// store.dispatch觸發(fā)mutation事件。
this.$store.dispatch('increment', {amount: 10})//帶payload情況,觸發(fā)事件
方法三:
在組件中還可以通過mapActions 輔助函數(shù)通過映射利用methods方法
import { mapActions } from 'vuex'
export default {
methods: {
...mapActions([
'increment', // 將 `this.increment()` 映射為 `this.$store.dispatch('increment')`
// `mapActions` 也支持載荷:
'incrementBy' // 將 `this.incrementBy(amount)` 映射為 `this.$store.dispatch('incrementBy', amount)`
]),
}
}
(5)、module模塊
當(dāng)應(yīng)用變得非常復(fù)雜時(shí),store 對(duì)象就有可能變得相當(dāng)臃腫。為了解決以上問題,將 store 分割成模塊(module)。每個(gè)模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進(jìn)行同樣方式的分割:
const moduleA = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... }
}
const store = createStore({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的狀態(tài)
store.state.b // -> moduleB 的狀態(tài)