← 返回首页
Vue-cli3基础教程(八)
发表时间:2020-11-20 15:23:06
vuex状态管理

如果你之前使用过vue.js,咱们就能深刻体会在vue中各个组件之间传值的痛苦,在vue中我们可以使用vuex来保存我们需要管理的状态值,值一旦被修改,所有引用该值的地方就会自动更新。Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex的应用场景出现在Vue多个组件之间需要共享数据或状态。

Vuex有几个核心概念:State、Getter、Mutation、Action、Module。

State:存储状态数据 Getter:从状态数据派生数据,相当于State的计算属性。 Mutation:存储用于同步更改状态数据的方法,默认传入的参数为state。 Action:存储用于异步更改状态数据,但不是直接更改,而是通过触发Mutation方法实现,默认参数为context。 Module:Vuex模块化。

它们之间的交互关系如下图(来源于官方文档)所示:

通过一个案例快速理解vuex.

实现步骤如下:

1.创建Vuex.Store实例

在store目录下新建index.js,定义了一个counter属性,和getters.getAvgCounter属性。 注意:getters.getAvgCounter属性仅仅实现了counter属性的平均值,并没有真正改变其值。

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const store = new Vuex.Store({
    state: {
        counter: 100
    },
    getters: {
        //获取平均值
        getAvgCounter(state) {
            return state.counter / 2;
        }
    }

});
export default store;

2.main.js文件中引入该文件

import Vue from 'vue'
import App from './App.vue'
import router from './router/router'
import store from './store/index'

Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App),
}).$mount('#app')

3.在vue视图组件中显示store中定义的数据

<template>
    <div>
        <p>
            Welcome Page!<br>
            在线人数是:{{$store.state.counter}}<br>
            使用getter获取的在线人数平均值是:{{$store.getters.getAvgCounter}}<br>
        </p>

    </div>
</template>

<script>
    export default {
        name: "Welcome",
        data(){
            return{

            }
        }
    }
</script>

<style scoped>

</style>

显示效果如下:

数据我们在页面是获取到了,但是如果我们需要修改counter值怎么办?如果需要修改store中的值唯一的方法就是提交mutation来修改。

4.在store中定义mutations

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const store = new Vuex.Store({
    state: {
        counter: 100
    },
    getters: {

        //获取平均值
        getAvgCounter(state) {
            return state.counter / 2;
        }
    },
    mutations: {
        addCounter(state, value) {
            console.log('in mutations->addCounter...');
            state.counter += parseInt(value);
        },

        subCounter(state, value) {
            console.log('in mutations->subCounter...');
            state.counter -= parseInt(value);
        }
    }
});
export default store;

5.在vue视图组件添加两个按钮,调用mutations里的方法。

<template>
    <div>
        <p>
            Welcome Page!<br>
            在线人数是:{{$store.state.counter}}<br>
            使用getter获取的在线人数平均值是:{{$store.getters.getAvgCounter}}<br>
            <input type="text" v-model="addNum"/><input type="button" @click="addNumber" value="增加counter的值"><br>
            <input type="text" v-model="subNum"/><input type="button" @click="subNumber" value="减少counter的值"><br>
        </p>

    </div>
</template>

<script>
    export default {
        name: "Welcome",
        data(){
            return{
                addNum: 0,
                subNum: 0
            }
        },
        methods:{
            addNumber(){
                this.$store.commit('addCounter',this.addNum);
            },
            subNumber(){
               this.$store.commit('subCounter',this.subNum);
           }
        }

    }
</script>

<style scoped>

</style>

运行效果:

6.定义action 但是,官方并不推荐我们这样直接去修改store里面的值,而是让我们去提交一个actions,在actions中提交mutation再去修改状态值。修改store/index.js如下:

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const store = new Vuex.Store({
    state: {
        counter: 100
    },
    getters: {

        //获取平均值
        getAvgCounter(state) {
            return state.counter / 2;
        }
    },
    mutations: {
        addCounter(state, value) {
            console.log('in mutations->addCounter...');
            state.counter += parseInt(value);
        },

        subCounter(state, value) {
            console.log('in mutations->subCounter...');
            state.counter -= parseInt(value);
        }
    },
    actions: {
        actionAddCounter(context, value) {
            context.commit("addCounter", value);
        },
        actionSubCounter(context,value){
            context.commit("subCounter",value);
        }
    }

});
export default store;

7.在vue视图组件中调用action

<template>
    <div>
        <p>
            Welcome Page!<br>
            在线人数是:{{$store.state.counter}}<br>
            使用getter获取的在线人数平均值是:{{$store.getters.getAvgCounter}}<br>
            <input type="text" v-model="addNum"/><input type="button" @click="addNumber" value="增加counter的值"><br>
            <input type="text" v-model="subNum"/><input type="button" @click="subNumber" value="减少counter的值"><br>
        </p>

    </div>
</template>

<script>
    export default {
        name: "Welcome",
        data(){
            return{
                addNum: 0,
                subNum: 0
            }
        },
        methods:{
            addNumber(){
                this.$store.dispatch("actionAddCounter",this.addNum);
            },
            subNumber(){
                this.$store.dispatch("actionSubCounter",this.subNum);
            }
        }

    }
</script>

<style scoped>

</style>

运行效果与上面完全相同。

8.mutations与actions的区别

actions的特点:

  1. 用于通过提交mutation改变数据。
  2. 会默认将自身封装为一个Promise。
  3. 可以包含任意的异步操作。

mutations的特点:

  1. 通过提交commit改变数据。
  2. 只是一个单纯的函数。
  3. 不推荐使用异步操作,异步操作会导致变量不能追踪。