Vuex状态管理

写作目的

每次搭建Vue项目的时候,都要去搜索一下状态管理如何一步步实现,而且总会出现这样或者那样的一些问题,而且每次的理解都会出现偏差,因此在这里记录一下,文章内容参考了 Ant Design Vue Pro

搭建步骤

第一步

安装vuex,安装命令如下所示:

npm i vuex

第二步

创建状态管理仓库,在 src 目录下创建 store 文件夹,在文件夹下分别创建 usergoods 两个文件夹、getters.jsindex.js 两个文件;接着在 goodsuser 文件夹下都创建 index.js 文件。 如下图所示

1.jpg

第三步

编写 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 中点击 添加 按钮的时候 goodsusers 的数量都会增加,因为这两个状态中都有 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 这样一个属性;如果没加,那么就需要注意不同状态下重名的问题。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容