Vuex的五个核心——state、getters、mutations、actions、modules

state相关内容请查看Vuex起步

一、Getters

1.介绍

  • 有时候我们需要从 store 中的 state 中派生出一些状态(对state中的变量进行一些操作或者说是建立函数),并且将这函数应用到多个组件时,如果通过复制函数,或者抽取到一个共享函数然后在多处导入它,这样的代码不够理想。所以就需要用到getters
  • getters类似于组件中的computed(计算属性),当它的依赖值发生了改变才会被重新计算

2.使用

  • getters中的函数有两个参数第一个是state,第二个是metters。
    在这里插入图片描述
    在组件中展示
    在这里插入图片描述

  • 如何向getters里的函数传递其他的参数?
    将函数返回值改为函数即可

        agefilter(state) {
            return (age) => {
                return state.person.filter((p) => {
                    return p.age >= age;
                })
            }
        }
    <p>{{$store.getters.agefilter(30)}}</p>

二、Mutations

1.携带额外参数(payload)

在之前提到过如何使用提交mutation修改store状态,那么如何在更新数据时,如何传递一些额外的数据?
在组件中通过commit mutation给store
在这里插入图片描述
接收传递过来的参数
在这里插入图片描述

2.两种提交风格

(1)普通方式的提交

this.$store.commit('increaseCount',count);

(2)对象风格的提交方式

      this.$store.commit({
        type: "increaseCount",
        count,
      });

对象风格的提交与(1)不同的是,最后接收的count是一个对象

        increaseCount(state, count) {
            // state.count += count;
            console.log(count);
            state.count += count.count;
        },

在这里插入图片描述

3.Mutation 需遵守 Vue 的响应规则

Vuex 的 store 中的状态是响应式的,那么当我们变更状态时,监视状态的 Vue 组件也会自动更新。这也意味着 Vuex 中的 mutation 也需要与使用 Vue 一样遵守一些注意事项:

  • 最好提前在你的 store 中初始化好所有所需属性。
    这些初始化的属性都会被加入到响应式系统中,而这些响应式系统会监听属性的变化,当属性发生改变时,会通知所有界面中用到该属性的地方,让界面发生更新
  • 当需要在对象上添加新属性时,现在的版本直接添加也能做到响应式,但是官网更推荐这样做:
Vue.set(obj, 'newProp', 123)

或者,用新对象替换老对象

state.obj = { ...state.obj, newProp: 123 }

如果要删除某个属性:

Vue.delete(state.obj,prop);

三、Actions

1.介绍

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。

也就是说,当某些情况下确实需要Vuex进行一些异步操作(网络请求……),就需要Action代替Mutation进行异步操作

2.使用

实现在点击修改名称按钮开始的1秒后,将名字修改为WRM:

  • 组件dispatch到action
    在这里插入图片描述

  • 由action执行完异步操作后,再由action提交mutation
    在这里插入图片描述

  • mutation

    mutations: {
        updateName(state) {
            state.info.name = "WRM";
        }
    },

四、Modules

1.介绍

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。

为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割

2.使用

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 的状态
(1)模块内的state

模块内的state会添加到store中的state,所以获取模块内的state属性:store.state.a.prop
在这里插入图片描述

(2)模块内的mutations

接收的第一个参数是模块的局部状态对象。调用和之前的store中的mutations一样

const modulesA = {
    state: {
        name: "WW"
    },
    mutations: {
        modifyName(state) {
            state.name = "WRM"
        }
    }
}
modiName() {
      this.$store.commit("modifyName");
    },
(3)模块内的getters

接收的前两个参数是分别是模块的局部状态对象,局部getter对象,根节点状态会作为第三个参数暴露出来。

    getters: {
        fullinfo(state, getters, rootState) {
            return rootState.address + state.name
        }
    }
    <p>{{$store.getters.fullinfo}}</p>

#####(4)模块内的actions

    actions: {
        add111(context) {
            setTimeout(() => {
                console.log(context);
            }, 1000)
        }
    }

打印结果:
在这里插入图片描述
当然,还有另外的一种es6的写法——对象的解构
在这里插入图片描述

3.命名空间

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

如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。

const store = new Vuex.Store({
  modules: {
    account: {
      namespaced: true,

      // 模块内容(module assets)
      state: () => ({ ... }), // 模块内的状态已经是嵌套的了,使用 `namespaced` 属性不会对其产生影响
      getters: {
        isAdmin () { ... } // -> getters['account/isAdmin']
      },
      actions: {
        login () { ... } // -> dispatch('account/login')
      },
      mutations: {
        login () { ... } // -> commit('account/login')
      },

      // 嵌套模块
      modules: {
        // 继承父模块的命名空间
        myPage: {
          state: () => ({ ... }),
          getters: {
            profile () { ... } // -> getters['account/profile']
          }
        },

        // 进一步嵌套命名空间
        posts: {
          namespaced: true,

          state: () => ({ ... }),
          getters: {
            popular () { ... } // -> getters['account/posts/popular']
          }
        }
      }
    }
  }
})

更多详细内容可以参考官网

五、项目结构

以购物车为例
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值