浅谈vuex actions和mutation的异曲同工
vuex说明:
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
包含的内容:
- state:驱动应用的数据源;
- view:以生命方式将state映射到视图;
- actions:响应在view上的用户输入导致的状态变化;
流程示意图
但是,当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:
多个视图依赖于同一状态。
来自不同视图的行为需要变更同一状态。
对于问题一,传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。
对于问题二,我们经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码。
因此,我们为什么不把组件的共享状态抽取出来,以一个全局单例模式管理呢?在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为!
另外,通过定义和隔离状态管理中的各种概念并强制遵守一定的规则,我们的代码将会变得更结构化且易维护。
适用于型单页应用
安装vuex
npm i vuex
新建文件夹store,建议目录
Actions 和 mutation
mutation:(必须是同步函数)
更改store中state值的唯一方法就是提交mutation,每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:
mutations: { addNum(state) { state.num ++ } }
你可以向 store.commit 传入额外的参数,即 mutation 的 载荷(payload):在大多数情况下,载荷应该是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读:
mutations: { addNum(state,Payload) { state.num +=Payload.amount } }
不能直接调用一个 mutation handler。这个选项更像是事件注册:“当触发一个类型为 increment 的 mutation 时,调用此函数。”要唤醒一个 mutation handler,你需要以相应的 type 调用 store.commit 方法:
//页面中的操作(一、不带参数) methods:{ add(){ this.$store.commit('addNum') } } //二、带参数的情况下 data(){ argument:{ amount:10 }, methods:{ add(){ this.$store.commit('addNum',this.arguments) } }
actions
Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。
mutations: { addNum(state,amount) { state.num +=amount }, someMutation(state) { setTimeout(()=>{ state.count-- },1000) } }, actions: { increment (context,args) { context.commit('addNum',args) } }, //另一种写法 actions: { increment ({commit},args) { commit('addNum',args) } }
Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters
分发Action
//页面中 methods:{ add(){ this.$store.dispatch('increment',this.pa.amount) } },
区别:
action和mutation都可以改变state中数据的状态,但是action可以处理异步函数可以在devtool中追踪数据变化,而mutation只可以处理同步函数,当处理异步函数的时候检测不到数据变化;
mutation 处理同步异步
mutations: { //同步 addNum(state,amount) { state.num +=amount }, //异步 someMutation(state) { setTimeout(()=>{ state.count-- },1000) } }
页面中操作
<template> <div> <p @click="add">同步{{num}}</p> <p @click="reduce">异步{{count}}</p> </div> </template> methods:{ //同步 add(){ this.$store.commit('increment',this.pa.amount) }, //异步 reduce(){ this.$store.commit('someMutation') } }
数据变化之前,浏览器中显示,devtool中的数据状态
当页面中的数据改变之后,追踪数据
action 处理同步异步
mutations: { addNum(state, amount) { state.num += amount }, someMutation(state) { state.count-- } }, actions: { increment({commit}, args) { commit('addNum', args) }, actionSomemution(context) { setTimeout(() => { context.commit('someMutation') }, 1000) } }
页面中
methods:{ add(){ this.$store.dispatch('increment',this.pa.amount) }, reduce(){ this.$store.dispatch('actionSomemution') } },
数据变化之前,浏览器中显示,与devtool中数据显示
操作之后数据变化,
----
小结:mutation只能处理同步函数,在devtools检测不到状态树中数据的变化,而actions可以处理同异步数据,可以在devtools检测数据变化,这样就好理解了