写作目的
每次搭建Vue项目的时候,都要去搜索一下状态管理如何一步步实现,而且总会出现这样或者那样的一些问题,而且每次的理解都会出现偏差,因此在这里记录一下,文章内容参考了
Ant Design Vue Pro
搭建步骤
第一步
安装vuex,安装命令如下所示:
npm i vuex
第二步
创建状态管理仓库,在
src目录下创建store文件夹,在文件夹下分别创建user和goods两个文件夹、getters.js和index.js两个文件;接着在goods和user文件夹下都创建index.js文件。 如下图所示

第三步
编写
goods/index.js文件,内容如下:
const goods= {
state: {
goods: [
{id: 1, name: 'Java', price: 10, num: 2},
{id: 2, name: 'Vue', price: 13, num: 21},
{id: 3, name: 'React', price: 15, num: 25}
]
},
mutations: {
addGoods(state, g) {
state.goods.push(g)
},
delGoods(state, idx) {
state.goods.splice(idx, 1)
}
},
actions: {
add({commit}, g) {
commit('addGoods', g)
},
del({commit}, idx) {
commit('delGoods', idx)
}
}
}
export default goods
编写
user/index.js,文件内容如下所示:
const user = {
state: {
users: [
{id: 1, name: 'zs'},
{id: 2, name: 'ls'},
{id: 3, name: 'ww'}
]
},
mutations: {
add(state, user) {
state.users.push(user)
},
del(state, idx) {
state.users.splice(idx, 1)
}
},
actions: {
add({commit}, user) {
commit('add', user)
},
del({commit}, idx) {
commit('del', idx)
}
}
}
export default user
编写
getters.js文件,内容如下所示:
const getters = {
user: state => state.user.users,
userLength: state => state.user.users.length,
goods: state => state.goods.goods
}
export default getters
编写
index.js文件,内容如下所示:
import Vue from 'vue'
import Vuex from 'vuex'
import goods from './goods'
import user from './user'
import getters from './getters'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
goods,
user
},
getters
})
第三步,配置
在
main.js中配置 vuex,配置代码如下所示:
import Vue from 'vue'
import App from './App.vue'
import store from './store'
new Vue({
store,
render: h => h(App),
}).$mount('#app')
第四步,在组件中使用
在
App.vue组件中演示状态管理的使用
<template>
<div id="app">
<h3>{{userLength}}</h3>
<ul>
<li v-for="u in user" :key="u.id">
{{u.id}} -- {{u.name}}
</li>
</ul>
<ul>
<li v-for="g in goods" :key="g.id">
{{g.id}} -- {{g.name}}
</li>
</ul>
<button @click="add({id: 5, name: 'xxxx'})">添加</button>
</div>
</template>
<script>
import {mapActions, mapGetters} from 'vuex'
export default {
computed: {
// 引入getters中的计算属性,需要在 computed 中引入
...mapGetters(['user', 'userLength', 'goods'])
},
methods: {
// 引入 user和goods 的 actions 中定义的 add 方法
...mapActions(['add'])
}
}
</script>
<style>
</style>
上面的代码存在着一定的问题,当我们在
App.vue中点击添加按钮的时候goods和users的数量都会增加,因为这两个状态中都有add方法,但是我们并没有指定使用哪个模块的add方法,例如说现在只想实现users的添加,那么该如何实现呢?
1). 在user/index.js对象定义的时候加上namspaced: true
2).在App.vue引入时候加上命名空间
const user = {
// 加上 namespaced
namespaced: true,
state: {
users: [
{id: 1, name: 'zs'},
{id: 2, name: 'ls'},
{id: 3, name: 'ww'}
]
},
mutations: {
add(state, user) {
state.users.push(user)
},
del(state, idx) {
state.users.splice(idx, 1)
}
},
actions: {
add({commit}, user) {
commit('add', user)
},
del({commit}, idx) {
commit('del', idx)
}
}
}
export default user
<template>
<div id="app">
<h3>{{userLength}}</h3>
<ul>
<li v-for="u in user" :key="u.id">
{{u.id}} -- {{u.name}}
</li>
</ul>
<ul>
<li v-for="g in goods" :key="g.id">
{{g.id}} -- {{g.name}}
</li>
</ul>
<button @click="add({id: 5, name: 'xxxx'})">添加</button>
</div>
</template>
<script>
import {mapActions, mapGetters} from 'vuex'
export default {
computed: {
// 引入getters
...mapGetters(['user', 'userLength', 'goods'])
},
methods: {
...mapActions('user', ['add'])
}
}
</script>
<style>
</style>
第五步,在普通的js中使用状态管理
实际应用中,我们不仅仅是在组件中使用到全局状态,在很多非vue组件中也要使用到状态管理的方式,例如: 1.路由组件中设置用户信息;2.设置全局样式;
import store from '@/store'
export function mutate() {
/**
* 1.调用user模块下 actions 中的 add 方法, 异步的方式
* 2. user/add 这样使用的前提是在 user/index.js 对象中加上了 namespaced: true
* 3. 如果没加 namespaced: true, 必须要保证不同的状态管理下方法不能重名
store.dispatch('user/add', {
id: 10,
name: 'QQ'
})
*/
/**
* 调用user模块下 mutations 中的 add 方法, 同步的方式
*/
store.commit('user/add', {
id: 10,
name: 'QQ'
})
}
注意: store.dispatch() 调用的是状态定义中actions中的方法,为异步的方式;store.commit() 调用的是 mutations 中的方法,为同步的方法;user/add 表示user模块下的add方法,这种调用方式的前提是在状态定义的时候加上了 namespaced: true 这样一个属性;如果没加,那么就需要注意不同状态下重名的问题。