【14】vuex2.0 之 mutation 和 action

我们的项目非常简单,当点击+1按钮的时候,count 加1,点击-1按钮的时候,count 减1.
1, mutation
The only way to actually change state in a Vuex store is by committing a mutation, 在vue 中,只有mutation 才能改变state. mutation 类似事件,每一个mutation都有一个类型和一个处理函数,因为只有mutation 才能改变state, 所以处理函数自动会获得一个默认参数 state. 所谓的类型其实就是名字,action去comit 一个mutation, 它要指定去commit哪个mutation, 所以mutation至少需要一个名字,commit mutation 之后, 要做什么事情,那就需要给它指定一个处理函数, 类型(名字) + 处理函数就构成了mutation. 现在store.js添加mutation.

const store = new Vuex.Store({
state: {
count:0
},
mutations: {
// 加1
increment(state) {
state.count++;
},
// 减1
decrement(state) {
state.count--
}
}
})

Vue 建议我们mutation 类型用大写常量表示,修改一下,把mutation 类型改为大写

mutations: {
// 加1
INCREMENT(state) {
state.count++;
},
// 减1
DECREMENT(state) {
state.count--
}
}

2, action
action去commit mutations, 所以还要定义action. store.js 里面添加actions.

const store = new Vuex.Store({
state: {
count:0
},
mutations: {
// 加1
INCREMENT(state) {
state.count++;
},
// 减1
DECREMENT(state) {
state.count--
}
},
actions: {
increment(context) {
context.commit("INCREMENT");
},
decrement(context) {
context.commit("DECREMENT");
}
}
})

action 和mutions 的定义方法是类似的,我们要dispatch 一个action, 所以actions 肯定有一个名字,dispatch action 之后它要做事情,就是commit mutation, 所以还要给它指定一个函数。因为要commit mutation ,所以 函数也会自动获得一个默认参数context, 它是一个store 实例,通过它可以获取到store 实例的属性和方法,如 context.state 就会获取到 state 属性, context.commit 就会执行commit命令。
其实actions 还可以简写一下, 因为函数的参数是一个对象,函数中用的是对象中一个方法,我们可以通过对象的解构赋值直接获取到该方法。修改一下 actions

actions: {
increment({commit}){
commit("INCREMENT")
},
decrement({commit}){
commit("DECREMENT")
}
}

3, dispatch action
现在就剩下dispatch action 了。什么时候dispatch action 呢? 只有当我们点击按钮的时候. 给按钮添加click 事件,在click 事件处理函数的中dispatch action.
打开increment.vue 组件,给两个按钮添加click 事件。

<template>
<div>
<button @click="increment">+1</button>
<button @click="decrement">-1</button>
</div>
</template> <script>
export default {
methods: {
increment(){
this.$store.dispatch("increment");
},
decrement() {
this.$store.dispatch("decrement")
}
}
}
</script>

其实像上面dispatch action 比较麻烦,如果有10 个按钮,我们要写10 个函数,且存在大量的重复,并且我们的事件处理函数名字和action的名字是一样的,这时vue 提供了mapAction 函数,它和mapState 是一样的,把我们的 action 直接映射到store 里面的action中。
像这种组件中的事件处理函数名字和action的名字是相同的,直接把 事件处理函数名字放到一个数组中。组件中的methods 修改如下:

<script>
import {mapActions} from "vuex";
export default {
methods: {
...mapActions(["increment", "decrement"])
}
}
</script>

如果事件处理函数名字和action的名字不同,给mapActions 提供一个对象,对象的属性是事件处理函数名字, 属性值是 对应的dispatch 的action 的名字。
我们把 +1 按钮的事件处理函数变改为 add,代码如下:

<template>
<div>
<button @click="add">+1</button> <!-- 事件处理函数变为add -->
<button @click="decrement">-1</button>
</div>
</template> <script>
import {mapActions} from "vuex";
export default {
methods: {
...mapActions(["decrement"]), // mapActions 对应做出改变
...mapActions({
add: "increment"
})
}
}

这时候我们单击按钮,就可以看到count 发生变化。
通过vuex 传递参数
很多时候,组件和组件之间还要传递参数,这些都要经过vuex。 在increment 组件内部增加一个输入框和一个按钮,点击按钮的时候,count 增加输入框内的值。

<template>
<div>
<div>
<button @click="increment">+1</button>
<button @click="decrement">-1</button>
</div>
// 增加内容
<div>
<input type="text" v-model="incrementValue">
<button @click="incrementWithValue">increment</button>
</div>
</div>
</template>

在组件内部dispatch action 的时候,它可以自定义参数,只要参数在它dispatch 的action名称 后面,依次列出来就可以了。 在这里,我们点击按钮的时候,触发一个incrementWithValue action, 并且带一个参数,就可以这样写 this.$store.dispatch(“incrementWithValue”, value), 整个increment.vue 组件如下:

<template>
<div>
<div>
<button @click="increment">+1</button>
<button @click="decrement">-1</button>
</div>
<div>
<input type="text" v-model="incrementValue">
<button @click="incrementWithValue">increment</button>
</div>
</div>
</template> <script>
import {mapActions} from "vuex";
export default {
data() {
return {
incrementValue: 0
}
},
methods: {
...mapActions(["increment","decrement"]),
incrementWithValue() {
this.$store.dispatch("incrementWithValue", this.incrementValue)
}
}
}
</script>

同样,actions 和mutations 中的处理函数也是一样,它除了可以得到默认参数外,还可以接受自定义的参数,我们自定义的参数,依次在默认参数后面列出来就可以了。 在store.js中分加增加incrementWithValue action和 INCREMENT_WITH_VALUE mutation

const store = new Vuex.Store({
state: {
count:0
},
mutations: {
// 加1
INCREMENT(state) {
state.count++;
},
// 减1
DECREMENT(state) {
state.count--
},
INCREMENT_WITH_VALUE(state, value){
state.count +=value;
}
},
actions: {
increment({commit}){
commit("INCREMENT")
},
decrement({commit}){
commit("DECREMENT")
},
incrementWithValue({commit}, value){
commit("INCREMENT_WITH_VALUE", parseInt(value))
}
}
})

错误处理
当我们给vuex 传参的时候,我们要检测参数的正确性,如果有错误需要进行处理
action 中如果是同步操作,就用try..catch 语句,组件中使用try…catch, 捕获action中抛出的错误。Increment.vue 组件中,incrementWithValue() 方法中修改如下:

methods: {
...mapActions(["increment","decrement"]),
incrementWithValue() {
try {
this.$store.dispatch("incrementWithValue", this.incrementValue)
}catch(error) {
alert(error)
}
}
}

同时store.js 中的action 也进行如下修改:

incrementWithValue({commit}, value){
let intValue = parseInt(value);
if(isNaN(intValue)){
throw "Not an Interger"
}else {
commit("INCREMENT_WITH_VALUE", intValue)
}
}

如果action 中进行的是异步操作,那就需要在回调函数中进行错误处理。

incrementWithValue({commit}, value){
let intValue = parseInt(value)
setTimeout(function() {
if(isNaN(intValue)) {
alert("Not an Interger")
}else {
commit("INCREMENT_WITH_VALUE", intValue)
}
}, 2000)
}

异步操作给出用户提示信息
首先,在我们的increment.vue中添加一个提示信息,简单给一个div 进行提示。用户提示信息的显示和隐藏,又涉及到一个状态,我们设为waiting, 需要在state 中进行添加。默认为false, 同时我们组件需要从state 中获取到初始状态。increment.vue 组件修改如下:

<template>
<div>
<div>
<button @click="increment">+1</button>
<button @click="decrement">-1</button>
</div>
<div>
<input type="text" v-model="incrementValue">
<button @click="incrementWithValue">increment</button>
</div>
<!-- 展示信息 -->
<div v-if ="show">
waiting
</div>
</div>
</template> <script>
import {mapActions} from "vuex";
export default {
data() {
return {
incrementValue: 0
}
},
// computed 从state 中获取初始状态
computed: {
show: function() {
return this.$store.state.waiting;
}
},
methods: {
...mapActions(["increment","decrement"]),
incrementWithValue() {
this.$store.dispatch("incrementWithValue", this.incrementValue)
}
}
}
</script>

mutation 去操作状态,所以增加两个muatation, 用于显示和隐藏waiting. action 中去触发这两个mutation. 整个state 如下:

const store = new Vuex.Store({
state: {
count:0,
// 新增waiting 状态
waiting: false
},
mutations: {
// 加1
INCREMENT(state) {
state.count++;
},
// 减1
DECREMENT(state) {
state.count--
},
INCREMENT_WITH_VALUE(state, value){
state.count +=value;
},
// 显示和隐藏waiting
SHOW_WAITING_MESSAGE(state){
state.waiting = true;
},
HIDE_WAITING_MESSAGE(state){
state.waiting = false;
}
},
actions: {
increment({commit}){
commit("INCREMENT")
},
decrement({commit}){
commit("DECREMENT")
},
incrementWithValue({commit}, value){
commit("SHOW_WAITING_MESSAGE");
let intValue = parseInt(value)
setTimeout(function() {
if(isNaN(intValue)) {
alert("Not an Interger")
}else {
commit("HIDE_WAITING_MESSAGE");
commit("INCREMENT_WITH_VALUE", intValue)
}
}, 2000)
}
}
})

注意:
mutation是同步的,只要comit muation, 它就会立即改变state , 这有利于我们追踪 状态的改变。如果 mution 之后,五分钟才改变state, 那就真不知道state 到底是哪个state了。
action 是异步的,还有的错误处理也都在这里操作。
【14】vuex2.0 之 mutation 和 action的更多相关文章
- Vuex2.0+Vue2.0构建备忘录应用实践
一.介绍Vuex Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化,适合于构建中大型单页应用. ...
- vuex2.0.0爬坑记录 -- mutations的第一个参数state不能解构
今天在学习vuex的过程中,遇到了一个很困扰人的问题,最终利用vuex的状态快照工具logger解决了问题. 问题是这样的,我在子组件中使用了mapState()函数来将状态映射至子组件中,使子组件能 ...
- vuex2.0源码分析
当我们用vue在开发的过程中,经常会遇到以下问题 多个vue组件共享状态 Vue组件间的通讯 在项目不复杂的时候,我们会利用全局事件bus的方式解决,但随着复杂度的提升,用这种方式将会使得代码难以维护 ...
- CentOS 7.2.1511编译安装Nginx1.10.1+MySQL5.7.14+PHP7.0.11
准备篇 一.防火墙配置 CentOS 7.x默认使用的是firewall作为防火墙,这里改为iptables防火墙. 1.关闭firewall: systemctl stop firewalld.se ...
- vuex2.0+两个小例子
首先vuex概念比较多,一定要搞懂里面的概念,可以参考官网Vuex2.0概念,我写此文的目的是希望能对前端爱好者提供个参考,加深对vuex2.0各核心概念的理解. 废话少说,直接上干货.这是官网上的一 ...
- Vuex2.0边学边记+两个小例子
最近在研究Vuex2.0,搞了好几天终于有点头绪了. 首先vuex概念比较多,一定要搞懂里面的概念,可以参考官网Vuex2.0概念,我写此文的目的是希望能对前端爱好者提供个参考,加深对vuex2.0各 ...
- vuex2 mapActions 报错 `unknown action type: xxxx`
export const setBreadCrumb = ({ dispatch }, data) => { dispatch('SET_BREADCRUMB', data) } 当调用的时候报 ...
- Asp.Net Core 2.0 之旅---@Html.Action
原文:Asp.Net Core 2.0 之旅---@Html.Action 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https: ...
- vuex mutation,action理解
1. 在store中分别注册mutation和action,action中用commit同步调用mutation来执行修改state,但是在组件中则使用dispatch异步调用action 2. 通俗 ...
随机推荐
- vue:vue router学习小结
序:本篇内容主要侧重对前端路由的理解,以vue的官方路由作为载体,进行一个简单介绍. 一.路由历史: 最早开始的时候,项目开发使用的是SSR,即服务端渲染.这个时候刷新页面,服务器返回的是全部的htm ...
- shell脚本,awk实现跳过文件里面的空行。
1.用awk '{if(!NF ){next}}1' file11 实现对文件里面的空行进行跳过操作,并输出结果. 2. awk '{if(!NF || /^#/){next}}1' file11 实 ...
- 操作系统(3)_CPU调度_李善平ppt
不只上面的四种,比如时间片到了也会引起调度. 具体的调度算法: fcfs简单,但是波动很大. 最高相应比算法,执行时间最长就应该等待的长点,比sjf多了一个等待时间的考虑. 硬件定时器和软件计数器共同 ...
- JS MarcoTasks MicroTasks
JS MarcoTasks MicroTasks 在JS的event loop中,有两种任务队列microtasks和macrotasks microtasks process.nextTick Pr ...
- 通过Tcode查找Badi或者客户出口
https://wiki.scn.sap.com/wiki/display/ABAP/Code+To+Find+BAdi Created by Naresh Reddy K, last modifie ...
- css清除浮动,清除子节点margin溢出问题
清除浮动 .clearfix:after{ content:”.”; display:block; height:0; clear:both; visibility:hidden; } 清除margi ...
- JZOJ 4735. 最小圈
Description 对于一张有向图,要你求图中最小圈的平均值最小是多少,即若一个圈经过k个节点,那么一个圈的平均值为圈上k条边权的和除以k,现要求其中的最小值 Input 第一行2个正整数,分别为 ...
- P1616 疯狂的采药【模板】
此题为NOIP2005普及组第三题的疯狂版. 此题为纪念LiYuxiang而生. 题目描述 LiYuxiang是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师.为此,他想拜附近最有威望的医师为师. ...
- 学习BootStrap3.3.4——敲完全局CSS样式
历时7小时- -(算上晚饭)终于敲完BootStrap CSS样式部分.还是第一次这么持久的敲纯前端,连JS都没有. 正好趁这机会熟悉了Sublime,主要是各个快捷键的用法.目前用到最多的: 而且s ...
- Android 完美解决bundle实现页面跳转并保留之前数据+传值
1.前言 前言: 昨天碰到了一个问题,我想实现页面跳转,采用了Bundle之后,再回到原来的页面,发现数据也没有了, 而且一直报错,网上查找了很多资料,发现要用一个startActivityForRe ...