VUEX的使用

70 阅读2分钟

前言

Vuex是一个专为 Vue.js 应用程序开发的状态管理模式。但是无法持久化,页面刷新即消失;

有错误的地方欢迎指正~

开始

  • 创建vuex仓库 如
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);


// 创建仓库
export default new Vuex.Store({
    state: {count:0},
    mutations: {
      increment(state) {
        state.count++
      }
    }
});
  • 在main.js里面引入仓库
import store from './store/index.js';

 

五个属性

state、getters、mutations、actions、modules。

  • state:vuex的基本数据,用来存储变量
  • getters:从基本数据(state)派生的数据,相当于state的计算属性
  • mutation:提交更新数据的方法,必须是同步的(如果需要异步使用action)。每个mutation都有一个字符串的事件类型(type)和一个回调函数(handler)。回调函数就是我们实际进行状态更改的地方,并且它会接受state作为第一个参数,提交载荷作为第二个参数。
  • action:和mutation的功能大致相同,不同之处在于==》1.Action提交的是mutation,而不是直接变更状态。2.Action可以包含任意异步操作。
  • modules:模块化vuex,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。

 

state

state就是数据源存放地,对应于一般Vue对象里面的data。state里面存放的数据是响应式的,Vue组件中从store中读取数据,若是store中的数据发生了改变,依赖这个数据的组件也会发生改变。

使用

在组件中使用时,最好放在计算属性中,这样在state变化时,页面也能动态渲染

computed: {
        getCount() {
            return this.$store.state.count;
        }
}

若需要获取多个状态,都设置为计算属性会使代码冗余,mapState辅助函数能解决这个问题

mapState辅助函数

mapState函数返回的是一个对象

在组件中使用,解决冗余问题

import {mapState} from 'vuex';
computed: mapState(
    {
        // this.computedCount === store.state.count
        computedCount: state => state.count,
        // this.nameCount === store.state.count
        nameCount: 'count'
    }
)
或
computed: mapState(
    // this.count === store.state.count
    ['count'],
)

扩展运算符

辅助函数与局部计算属性一起使用

computed: {
    ...mapState(
        {
            // this.computedCount === store.state.count
            computedCount: state => state.count,
            // this.nameCount === store.state.count
            nameCount: 'count'
        }
    )
}

 

getters

从state 中派生出一些状态,可以看成计算属性,可以通过属性或函数的方式访问获取

 

属性访问与方法访问

getters: {
        // 属性访问
        count100: (state) => state.count + num,
        // 方法访问
        count_num_x100: state => number => state.count * number * num
    },


computed: {
        // 属性访问
        count100() {
            return this.$store.getters.count100;
        },
        // 方法访问
        count_num_x100() {
            return this.$store.getters.count_num_x100(2);
        }
    }

 

mapGetters 辅助函数

用法与mapState类似

mutations

  • 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation
  • 注意Mutations里面的函数必须是同步操作,不能包含异步操作
mutations: {
    increment(state) {
        state.count++;
    },
    incrementNum(state, number) {
        state.count += number;
    }
}


methods: {
    incrementCount() {
        this.$store.commit('increment');
    },
    incrementCountNum() {
        this.$store.commit('incrementNum', 20);
    }
}

mapMutations辅助函数

methods: {
  ...mapMutations([
    'increment',
    'incrementNum'
]
}


<button class="fd-btn-a" @click="increment">count++</button>
<button class="fd-btn-a" @click="incrementNum(20)">incrementNum++</button>

 

actions

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。
  • Action 通过 store.dispatch 方法触发:
actions: {
    incrementAsync({commit}) {
        setTimeout(() => {
            commit('increment');
        }, num * num2);
    }
}
incrementAsync() {
    this.$store.dispatch('incrementAsync');
}

 

mapActions 辅助函数

使用方法与mapState类似

 

组合 Action

store.dispatch 可以处理被触发的 action 的处理函数返回的 Promise,并且 store.dispatch 仍旧返回 Promise

actions: {
    incrementAsync({commit}) {
        return new Promise((resolve) => {
            setTimeout(() => {
                commit('increment');
                resolve();
            }, num * num2);
        });
    }
}
incrementAsync() {
    this.$store.dispatch('incrementAsync').then(() => {
        alert(1);
    });
}

 

module

  • 当应用变得非常复杂时,store 对象就有可能变得相当臃肿。Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter。
  • 对于模块内部的 action,局部状态通过 context.state 暴露出来,根节点状态则为 context.rootState:

使用模块中的state、getters,mutation,action

注意,除了state以外,所有的getters、mutation、actions都是全局的,使用方式与全局使用方式一致,若要将所有属性都局部化,模块定义里定义namespaced: true即可,以下使用都是namespaced: true的情况下的使用方式:

// state
countA: state => state.a.count

// getters
this.$store.getters['a/count100']

// mutations
increment: 'a/increment',

// ations
incrementAsync() {
    this.$store.dispatch('a/incrementAsync').then(() => {
        alert('a');
    });
    this.$store.dispatch('b/incrementAsync').then(() => {
        alert('b');
    });
}

模块嵌套

在模块中直接写嵌套

在moduleB中嵌套moduleC

const moduleC = {
    namespaced: true,
    state: {count: 3},
    getters: {count100: (state) => state.count * num}


};

若模块c没有定义namespaced,那么c可以访问b的命名空间,c可以使用b中的getters等

通过动态注册嵌套

store.registerModule(['b', 'c'], {state: {count: 3}});

 

严格模式

  • 开启strict:true,无论何时发生了状态变更且不是由 mutation 函数引起的,将会抛出错误。这能保证所有的状态变更都能被调试工具跟踪到。