Vuex全局的狀態(tài)統(tǒng)一管理,解決組件之間狀態(tài)共享和數(shù)據(jù)通信的問題。
第一步
store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex) // 使用插件
// 導(dǎo)出store實例
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
}
})
第二步
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
new Vue({
router,
store, // 增加store屬性,值是導(dǎo)出store的實例
render: h => h(App)
}).$mount('#app')
通過上面兩個步驟,每個組件中都有了$store屬性,就是我們創(chuàng)建的容器。里面有commit,dispatch,state,getters,actions,mutations,在每個組件中可以通過this.$store打印出來看看。
開始使用
定義狀態(tài)
export default new Vuex.Store({
state: {
count: 1 // state中定義響應(yīng)式的數(shù)據(jù)
}
})
使用狀態(tài):在store的state中定義的狀態(tài)count,在組件中可以使用this.$store.state.count獲取。
定義mutations
在store的mutations中添加對應(yīng)的方法
export default new Vuex.Store({
state: {
count: 1 // state中定義響應(yīng)式的數(shù)據(jù)
},
mutations: {
addTen (state, num) {
state.count = state.count + num
}
},
actions: {
}
})
提交mutations
組件中通過commit提交mutations去修改state中的狀態(tài)
this.$store.commit('addTen', 10)
定義actions
在store的actions中添加對應(yīng)的方法
export default new Vuex.Store({
state: {
count: 1
},
mutations: {
addTen (state, num) {
// 第一個參數(shù)是狀態(tài),第二個是傳入的參數(shù)
state.count = state.count + num
}
},
actions: {
minusTen ({commit}, num) {
// 第一個參數(shù)是store實例,第二個是傳入的參數(shù)
setTimeout(() => {
commit('addTen', num)
}, 1000)
}
}
})
派發(fā)動作
組件中可以使用dispatch派發(fā)一個動作,來觸發(fā)actions中的方法,actions可以異步的提交mutations去修改state中的狀態(tài)
this.$store.dispatch('minusTen', 10)
actions主要是復(fù)用,封裝代碼,處理異步,請求接口等等,真正修改狀態(tài)放到了mutations中處理
定義getters
在store的getters中添加對應(yīng)的方法
export default new Vuex.Store({
state: {
count: 1,
person: {
name: '張三'
}
},
getters: {
getName (state) {
// getters是同步的
return state.person.name
}
}
})
使用getters
this.$store.getters.getName
getters定義的方法相當于計算屬性,相當于定義在computed一樣,有緩存,依賴改變會重新計算。
組件代碼演示
<template>
<div class="hello">
<h1>{{ this.$store.state.count }}</h1>
<h1>{{ this.$store.getters.getName }}</h1>
<button @click="syncAdd">同步加10</button>
<button @click="asyncAdd">異步加10</button>
</div>
</template>
<script>
export default {
methods: {
syncAdd () {
this.$store.commit('addTen', 10)
},
asyncAdd () {
this.$store.dispatch('minusTen', 10)
}
}
}
</script>
簡寫
上面的寫法都是在this.$store中獲取屬性或方法進行操作。
this.$store.state.count
this.$store.getters.getName
this.$store.commit('addTen', 10)
this.$store.dispatch('minusTen', 10)
但是這些操作寫起來比較繁瑣,每次都要寫this.$store,為了簡寫,所以vuex提供了一些映射的方法,直接導(dǎo)入到組件中就可以使用了。
<template>
<div class="hello">
<h1>{{ count }}</h1>
<h1>{{ getName }}</h1>
<button @click="syncAdd">同步加10</button>
<button @click="asyncAdd">異步加10</button>
</div>
</template>
<script>
import {mapActions, mapState, mapMutations, mapGetters} from 'vuex'
export default {
computed: {
...mapState(['count']),
...mapGetters(['getName'])
},
methods: {
syncAdd () {
this.addTen(10)
},
asyncAdd () {
this.minusTen(10)
},
...mapActions(['minusTen']),
...mapMutations(['addTen'])
}
}
</script>
有一點需要說明的是,使用擴展運算符,表示這些方法返回的都是對象,mapState和mapGetters需要定義在計算屬性中,因為他們定義的數(shù)據(jù)是響應(yīng)式的。而mapActions和mapMutations需要定義在methods中。
拆分模塊
狀態(tài)是可以分層的,當一個項目維護的狀態(tài)太多,可以拆分成單獨的模塊,在定義store中有個modules屬性,里面可以定義單獨的模塊。
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
'page1': {
namespaced: true,
state: {
count: 1,
person: {
name: '張三'
}
},
mutations: {
addTen (state, num) {
state.count = state.count + num
}
},
actions: {
minusTen ({commit}) {
setTimeout(() => {
commit('addTen', 10)
}, 1000)
}
},
getters: {
getName (state) {
return state.person.name
}
}
}
}
})
在組件中這樣用
<template>
<div class="hello">
<h1>{{ count }}</h1>
<h1>{{ getName }}</h1>
<button @click="syncAdd">同步加10</button>
<button @click="asyncAdd">異步加10</button>
</div>
</template>
<script>
import {mapActions, mapState, mapMutations, mapGetters} from 'vuex'
export default {
computed: {
...mapState('page1', ['count']),
...mapGetters('page1', ['getName'])
},
methods: {
syncAdd () {
this.addTen(10)
},
asyncAdd () {
this.minusTen(10)
},
...mapActions('page1', ['minusTen']),
...mapMutations('page1', ['addTen'])
}
}
</script>
每個方法都傳了兩個參數(shù),第一個參數(shù)指定命名空間,第二個參數(shù)是對應(yīng)的屬性,為了進一步簡寫,可以通過幫助函數(shù)指定命名空間,指定當前組件在使用的模塊。
<template>
<div class="hello">
<h1>{{ count }}</h1>
<h1>{{ getName }}</h1>
<button @click="syncAdd">同步加10</button>
<button @click="asyncAdd">異步加10</button>
</div>
</template>
<script>
import { createNamespacedHelpers } from 'vuex'
// 創(chuàng)建幫助函數(shù)指定命令空間
let { mapActions, mapState, mapMutations, mapGetters } = createNamespacedHelpers('page1')
export default {
computed: {
...mapState(['count']),
...mapGetters(['getName'])
},
methods: {
syncAdd () {
this.addTen(10)
},
asyncAdd () {
this.minusTen(10)
},
...mapActions(['minusTen']),
...mapMutations(['addTen'])
}
}
</script>
不使用簡寫
this.$store.getters['page1/getName']
this.$store.state.page1.count
this.$store.commit('page1/addTen', 10)
this.$store.dispatch('page1/minusTen', 10)