vuex2

79 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第18天,点击查看活动详情juejin.cn/post/714765…

Mutation需要遵守Vue的响应规则

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

  1. 最好提前在你的store中初始化好所有所需属性
  2. 当需要在对象上添加新属性时,你应该
    • 使用vue.use(obj,'newProp',123),或者
    • 以新对象替换老对象,例如,使用对象展开运算符我们可以这样写:

image.png

使用常量替代mutation事件类型

使用常量替代mutation事件类型在各种Flux实现中是很常见的模式。这样可以使linter之类的工具发挥作用,同时把这些常量放在单独的文件中可以让你的代码合作者对整个app包含的mutation一目了然:
注意:要用[]括号括起来,可以在后面注释该常量具体用来做什么的,使别人阅读代码更加的容易,团队协作更高效。

image.png

mutation必须是同步函数

现在想像,我们正在debug一个app并且观察devtool中的mutation日志。每一条mutation被记录。devtools都需要捕捉到前一状态和后一状态的快照。然而,在上面的例子中mutation中的异步函数中的回调让这不可能完成:因为当mutation触发的时候,回调函数还没有被调用,devtools不知道什么时候回调函数实际上被调用---实质上任何在回调函数中进行的状态的改变都是不可追踪的。

在组件中提交mutation

可以在组件中使用this.$store.commit('...')提交mutation,或者使用mapMutations辅助函数将数组中的methods映射为store.commit调用(需要在根节点注入store)。

image.png

image.png

image.png

actions

actions写法类似于mutation,不同在于:

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

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

image.png

image.png
context的console结果

image.png

组合action

action通常是异步的,那么如何知道action是什么时候结束呢?更重要的是,我们如何才能组合多个action,以处理更加复杂的异步流程
首先,需要明白store.dispatch可以处理被触发的action的处理函数返回的Promise,并且store.dispatch仍旧返回promise:
下面的示例会先调用actionA, then方法之后调用后面的操作:

image.png 可以变成

image.png
另一个action中

image.png
最后,如果利用async/await,我们如下所示:

image.png
注意一个store.dispatch在不同模块中可以触发多个action函数。在这种情况下,只有当所有触发函数完成后,返回的promise才会执行。

modules

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时。store对象就有可能变得相当臃肿。
为了解决以上问题。vuex允许我们将store分割成模块。每个模块拥有自己的state、mutation、action、getter、甚至是嵌套子模块---从上至下进行同样方式的分割:

image.png

image.png

image.png

命名空间

默认情况下,模块内部的action、mutation和getter是注册在全局命名空间的---这样使得多个模块能够对同一mutation或action作出相应。
如果希望模块具有更高的封装度和复用性,可以通过添加namepaced:true的方式使其成为带命名空间的模块。当模块被注册之后,它的所有getter、action以及mutation都会自动根据模块注册的路径调整命名。例如:

image.png
启动了命名空间的getter和action会收到局部化的getter,dispatch和commit。换言之,你在使用模块内容时不需要在同一模块内额外添加空间名前缀。更改namespaced属性后不需要修改模块内的代码。(也就是前面的例子不需要在写点a和点b了)

项目结构

vuex并不限制代码结构,但是,它规定了一些需要遵守的规则:

  1. 应用层级的状态应该集中到单个store对象中
  2. 提交mutation是更改状态的唯一方法,并且这个过程是同步的。
  3. 异步逻辑都应该封装到action里面 目录:

image.png

开发环境与发布环境

不要再发布环境下启用严格模式!严格模式会深度监测状态树来检测不合规的状态变更--请确保再发布环境下关闭严格模式,以避免性能损失。

image.png

vuex核心流程中的主要功能

  • vue Components是vue组件,组件会触发(dispatch)一些事件活动做。
  • 在组件中发出的动作,肯定是想获取或者改变数据的,但是在vuex中,数据是集中管理的,不能直接去更改数据,所以会把这个动作提交(commit)到mutations中
  • 然后mutations就去改变(mutation)state中的数据
  • 当state中的数据被改变之后,就会重新渲染(render)到vue Components中去,组件展示更新后的数据,完成一个流程。

各模块在核心流程中能够的主要功能

  • vue Components:vue组件。HTML页面是哪个,负责接收用户操作等交互行为,执行dispatch方法触发对应action进行回应。
  • dispatch:操作行为触发方法,是唯一一个能执行action的方法
  • actions:操作行为处理模块。负责处理vue。components接收到的所有交互行为。包含同步/异步操作,支持多个同名方法,按照注册的顺序以此触发。向后台API请求的操作就在这个模块中进行。包括触发其他action以及提交mutation的操作。该模块提供了promise的封装,以支持action的链式触发。
  • commit:状态改变提交操作方法。对mutation进行提交。是唯一能执行mutation的方法
  • mutations:状态改变操作方法。是vuex修改state的唯一推荐方法,其他修改方式在严格模式下将会报错,该方法只能进行同步操作,且方法名只能全局唯一。操作之中会有一些hook暴露出来,已进行state的监控等。
  • state:页面状态管理容器对象。集中存储vueComponents中data对象的零散数据,全局唯一。以进行同一的状态管理。页面显示所需的数据从该对象中进行读取,利用vue的细粒度数据响应机制来进行高效的状态更新。
  • getters:state对象读取方法。多数用于数据格式化。