Vuex

Posted HelloHello233

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vuex相关的知识,希望对你有一定的参考价值。

基本的用法就是把一个vue应用中所有的状态都放进store中,然后在computed对象中读取store(这里实际上有两种方式,一是注入store(this.$store.state.xx),二是直接访问全局的store,store.state.xxx)

以上每个状态都需要放到computed中返回,即每个状态都要对应computed中的一个方法,很麻烦,这时候可以使用mapState,提供了简洁的computed对象写法

对于一个比较长的store表达式,如 this.$store.state.todos.filter(todo => todo.done).length,可以放到computed中,也可以放到store的getters对象中。前者属于组件,不方便多组件间的复用,而后者在Store中,store独立于组件,可多组件共用一个store

通过getter可以返回一个值也可以返回一个函数,返回函数有利于state的封装

mapGetters提供了getters的简洁写法

直接修改state的方式是commit一个mutation(处理同步),mapMutataions提供commit mutation的简洁写法。

Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。

异步的处理流程:在外部通过store.dispatch发送一个action(执行一个action函数),函数内允许执行异步操作,完成后调用context.commit提交一个mutation,来同步地通知显示结果。因为dispatch返回一个promise,所以也可以在外部注册一个回调函数,来告知异步结果。当外部的注册的函数执行时,也代表这个action(异步操作)已经完成。

action函数也可以写成async的,内部使用await来等待promise。

模块

因为一个vue应用的所有状态都放在了单独的store中,不可避免地会导致store体积较大,可以将store拆分成多个module。module和store具有相同的属性(以上提到的context就是一个module),所以model可以实现多层嵌套(通过modules属性来指定模块):

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

 

默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应:

<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vuex"></script>
<script>
    const moduleA = {
        mutations: {
            query:function(){
                console.log("query in A")
            }
        }
    }

    const moduleB = {
        mutations: {
            query:function(){
                console.log("query in B")
            }
        }
    }
    const store = new Vuex.Store({
        modules: {
            a: moduleA,
            b: moduleB
        }
    })
    store.commit("query");
</script>

 

以上运行结果,两个模块中的query方法都会被执行。

对于“注册在全局命名空间下”的理解:就像是模块中的内容直接写在了外部的store内一样,而对于多个模块,外部的store就是全部命名空间。这样一来,触发Store.commit当然会执行当下的mutation了。

或者这么说,模块的内容默认是注册到父空间上,store所在的是全局空间(顶层空间),以上的a和b两个模块的父空间刚好就是store全局空间。

如何打破以上这种默认情况,让模块的内容注册到自己的命名空间内呢?只需要在模块内加上一句说明即可:

const moduleB = {
        namespaced:true,
        mutations: {
            query:function(){
                console.log("query in B")
            }
        }
    }

 

重新执行以上代码,B模块中的query就不执行了,而只执行了A中的query。因为多了一句声明,B中的内容已经注册到自己的命名空间下了,而不是全局空间。

那如何执行B中的query呢?只需要在commit的时候加上命名空间:

store.commit("b/query");

 

运行效果就是仅仅执行了B模块中的query。

模块内获取到的参数,如:state,getters,dispatch、commit等都是指向当前空间,如果想访问根空间,则使用rootXX、或者通过参数指定{root:true},指明要访问全局空间。

 

以上的模块直接写在了stroe内,属于静态的模块注册。可以通过stroe.registerModule来动态注册模块

 

以上是关于Vuex的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段13——Vue的状态大管家

项目集成 vue-router 和 vuex

手把手教你学vue-4(vuex)

Vue 教程(四十九)Vuex 核心概念和项目结构

Vue 教程(四十九)Vuex 核心概念和项目结构

Vue 教程(四十九)Vuex 核心概念和项目结构