一、Vuex Store介绍

1、vuex带来的好处:

  • 组件之间数据共享
  • 组件中数据持久化
  • 使用 Vuex 可用使数据流变得清晰、可追踪、可预测
  • 使用 Vuex 管理 store 会大大提高项目的稳定性、扩展性

2、Vuex核心:
在这里插入图片描述

  • state:存储基本数据
  • getter:从基本数据(state)派生的数据,相当于state的计算属性
  • mutation : store中更改state数据状态的唯一方法(mutations必须是同步函数)
  • action: 包含异步操作(请求API方法)、回调函数提交mutaions更改state数据状态,使之可以异步。
  • module: 模块化Vuex(将store分割成不同的模块)

vuex中文文档参考资料
vuex推荐视频学习入口

二、安装引入

本项目示例通过vue cli4脚手架搭建

1.引入vuex库

npm install vuex --save

2.引入store模块

在main.js引入store模块

import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";

createApp(App)
  .use(store)   
  .use(router)
  .mount("#app");

三、使用操作

1.基本使用

以下是通过对用户信息的用户名进行数据操作为例
(1) store目录下的的index.js

import {createStore} from 'vuex'

export default createStore({
    state: {
        username:'lss0555'
    },
    mutations: {
        setUserName(state,username){
            state.username=username
        }
    },
    getters:{
      getUserName(state){
         return 'my name is '+state.username
      } 
    },
    actions: {
        getUserInfo({ state,commit }){
            new Promise(resolve => {
                setTimeout(() => {
                    //随机生成一个随机数1-10
                    var num=Math.floor((Math.random()*10)+1)
                    //提交修改username属性
                    commit("setUserName",'lss00'+num);
                    //返回处理结果
                    resolve();
                }, 1000);
            });
        }
    },
    modules: {}
})

(2) 用户组件UserInfo.vue

<template>
    <h2>获取用户名方式1{{username1}}</h2>
    <h2>获取用户名方式2{{username2}}</h2>
    <h2>获取用户名方式3{{username3}}</h2>
    <h2>获取用户名方式4{{$store.state.username}}</h2>

    <button @click="updateName">修改用户名方式1</button>
    <button @click="setUserName('lss0888')">修改用户名方式2</button>
    <button @click="setUserName1('lss0999')">修改用户名方式3</button>
    <div/>
    <button @click="syncUpdateName">异步获取用户名1</button>
    <button @click="getUserInfo">异步获取用户名2</button>
    <button @click="syncUpdateName1">异步获取用户名3</button>
</template>

<script>
    import {mapState, mapActions, mapMutations} from 'vuex'

    export default {
        name: "userinfo",
        data() {
            return {}
        },
        computed: {
            username1() {
                return this.$store.state.username
            },
            ...mapState({
                username2: state => state.username,
                username3(state) {
                    return state.username;
                }
            }),
        },
        methods: {
            updateName() {
                this.$store.commit('setUserName', 'lss0666')
            },
            syncUpdateName() {
                this.$store.dispatch('getUserInfo')
            },
            ...mapMutations(['setUserName']),
            ...mapMutations({
                setUserName1: "setUserName"
            }),
            ...mapActions(["getUserInfo"]),
            ...mapActions({
                syncUpdateName1: "getUserInfo"
            }),
        }
    }
</script>

<style scoped>

</style>
其中:

(1) 获取state数据的方法

//方式一
this.$store.state.username

...mapState({
	//方式二
    username2: state => state.username,
    //方式三
    username3(state) {
   		return state.username;
 	}
})

(2)通过getter方法获取对state数据处理后的数据

//index.js
getters:{
  getUserName(state){
     return 'my name is '+state.username
  }
},
//UserInfo.vue
mounted(){
  this.username4=this.$store.getters.getUserName
},

(3)通过Mutations修改state数据方法

//方式一
this.$store.commit('setUserName', 'lss0666')

//方式二
...mapMutations(['setUserName']),

//方式三
...mapMutations({
  setUserName1: "setUserName"
}),

(4)通过Action异步调用方法

//方式一
this.$store.dispatch('getUserInfo')

//方式二
...mapActions(["getUserInfo"]),

//方式三
...mapActions({
   syncUpdateName1: "getUserInfo"
}),

效果图
在这里插入图片描述

2.store文件优化

由于在store目录下的index.js里包含着state,actcion,mutations,getters模块,如果你的 store 文件太大,将不利于后期代码的维护,下面则对该文件进行优化,只需将 action、mutation 和 getter 分割到单独的文件在store目录下,在store目录下新建state.js,actions.js,getters.js,mutations.js目录,如下:
(1) state.js

export default {
    username:'lss0555'
}

(2) getters.js

export default {
    getUserName(state){
        return 'my name is '+state.username
    }
}

(3) mutations.js

export default {
    setUserName(state,username){
        state.username=username
    }
}

(4)actions.js

export default {
    getUserInfo({ state,commit }){
        new Promise(resolve => {
            setTimeout(() => {
                //随机生成一个随机数1-10
                var num=Math.floor((Math.random()*10)+1)
                //提交修改username属性
                commit("setUserName",'lss00'+num);
                //返回处理结果
                resolve();
            }, 1000);
        });
    }
}

(5)index.js

import {createStore} from 'vuex'
import state from './state.js'
import actions from  './actions.js'
import getters from  './getters.js'
import mutations from './mutations.js'

export default createStore({
    state,
    actions,
    getters,
    mutations,
    modules: {}
})
3.store分模块modules化

对于大型应用,我们会希望把 Vuex 相关代码分割到模块中。将以上的用户信息模块分为用户模块user以及用户模块1两部分。则目录为以下:
在这里插入图片描述
其中,user与user1下面是基本一致代码,user与user1目录下的index.js内容以下:

import state from './state.js'
import actions from  './actions.js'
import getters from  './getters.js'
import mutations from './mutations.js'

export default {
    namespaced:true,
    state:state,
    actions:actions,
    getters:getters,
    mutations:mutations
}

其中加入namespaced属性为true,则之后在不同页面中引入getter、actions、mutations时,需要加上所属的模块名。

页面UserInfo.vue如下:

<template>
    <h1>用户模块一</h1>
    <h2>获取用户名方式1{{username1}}</h2>
    <h2>获取用户名方式2{{username2}}</h2>
    <button @click="updateName">修改用户名方式1</button>
    <button @click="setUserName('lss0888')">修改用户名方式2</button>
    <div/>
    <button @click="syncUpdateName">异步获取用户名1</button>
    <button @click="syncUpdateName2">异步获取用户名2</button>


    <h1>用户模块二</h1>
    <h2>获取用户名方式1{{username3}}</h2>
    <h2>获取用户名方式2{{username4}}</h2>

    <button @click="updateName1">修改用户名方式1</button>
    <button @click="setUserName1('lss0777')">修改用户名方式2</button>
    <div/>
    <button @click="syncUpdateName1">异步获取用户名1</button>
    <button @click="syncUpdateName3">异步获取用户名2</button>
</template>

<script>
    import {mapState, mapActions, mapMutations} from 'vuex'

    export default {
        name: "userinfo",
        data() {
            return {}
        },
        computed: {
            username1() {
                return this.$store.state.user.username
            },
            username3() {
                return this.$store.state.user1.username
            },
            ...mapState({
                username2: state => state.user.username,
                username4: state => state.user1.username,
            }),
        },
        methods: {
            //use模块
            updateName() {
                this.$store.commit('user/setUserName', 'lss0666')
            },
            syncUpdateName() {
                this.$store.dispatch('user/getUserInfo')
            },
            ...mapMutations('user',{
                setUserName: "setUserName"
            }),
            ...mapActions('user',{
                syncUpdateName2: "getUserInfo"
            }),

            //user1模块
            updateName1() {
                this.$store.commit('user1/setUserName', 'lss0333')
            },
            syncUpdateName1() {
                this.$store.dispatch('user1/getUserInfo')
            },
            ...mapMutations('user1',{
                setUserName1: "setUserName"
            }),
            ...mapActions('user1',{
                syncUpdateName3: "getUserInfo"
            }),
        }
    }
</script>

<style scoped>

</style>

user与user1模块虽然代码一样,但是都是单独的模块,数据互不干扰。
效果图如下:
在这里插入图片描述

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐