为什么vuex的Mutations是同步,而Actions是异步
vuex[1]的mutations
与actions
有什么区别,除了用法上mutation
是同步,actions
是异步,这里的同步与异步指的是commit
ordispatch
?并不是,同步指mutations
方的内部是同步的,而actions
内部可以是异步的,并且修改数据只能在mutations
中修改,在actions
中异步操作的副作用结果是通过mutations
来记录。本文是一篇笔者记录vuex
关于mutations
与actions
的笔记。
正文开始...
避坑
如果使用vue-cli2
模版搭建的基础项目,注意,如果使用vue
版本是2,当你默认安装vuex
肯定是4.x
版本了,这里需要注意的是,你要降低vuex
版本到3.x
版本,不然store
挂载不到vue
上,访问的this.$store就是undefined
mutation
当我们修改数据,只能通过mutation
修改state
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export const store = new Vuex.Store({
state: {
data: []
},
mutations: {
storeData (state, payload) {
state.data = state.data.concat(payload)
}
}
})
在页面中
import { mockFeatchData } from '@/mock'
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
},
computed: {
...mapState({
dataList: state => state.data
})
},
methods: {
handleData () {
mockFeatchData().then(res => {
this.$store.commit('storeData', res)
})
}
}
}
我们修改数据就是$store.commit('eventName', payload)
,当我们触发commit
时,实际上是已经在异步请求回调里获取了数据。
但是官方在描述mutation
有这么说,mutation
内部必须是同步函数,异步会导致内部状态难以追踪,devtool
难以追踪state
的状态
...
mutations: {
storeData (state, payload) {
mockFeatchData().then((res) => {
console.log(res)
state.data = state.data.concat(res)
})
}
},
也就是说上面这段代码,当我们在mutations
中的storeData
中使用了异步函数,我们在$store.commit('storeData')
时,很难追踪state
的状态,因为在commit触发mutations事件时,异步的回调函数
不知道什么时候执行,所以难以追踪。
mutations
是同步事务,假设在mutations
有多个异步的调用,你很难确定这些异步哪些先执行,很难追踪state
的变化,所以也给调试带来了一定难度
话说回来,这么写也确实是可以做到更新state的值
,如果我不用vuetool
这个工具,貌似也没毛病
既然mutations
是同步的事情,那么异步官方就使用了actions
方案
actions
actions
里面可以做异步操作,但是并不是直接修改数据,提交的是mutations
里面的方法
mutations: {
storeData (state, payload) {
state.data = state.data.concat(payload)
}
},
actions: {
setStoreData ({ commit }) {
mockFeatchData().then((res) => {
commit('storeData', res)
})
}
}
在页面中就是这样触发actions
的
methods: {
handleData () {
this.$store.dispatch('setStoreData')
}
}
我们把异步操作放在了actions
的方法里面,你会发现mockFeatchData
这是一个异步操作后的结果,然后通过commit
传给了mutations
中
在actions
执行异步操作,将结果给了mutations
,mutations
中同步修改状态state
,使得actions
的操作在mutations
中有记录。
在actions
中也可以有多个异步操作
mutations: {
storeData (state, payload) {
state.data = state.data.concat(payload)
},
storeText (state, payload) {
state.text = payload
}
},
actions: {
setStoreData ({ commit }) {
mockFeatchData().then((res) => {
console.log(res, '111')
commit('storeData', res)
})
},
setStoreText ({ dispatch, commit }, payload) {
dispatch('setStoreData').then(() => {
console.log(222)
commit('storeText', payload)
})
}
}
页面上是这样触发actions
的
handleText () {
this.$store.dispatch('setStoreText', `hello,${Math.random()}`)
}
这里我们也可以用对象的方式
handleText () {
this.$store.dispatch({
type: 'setStoreText',
payload: `hello,${Math.random()}`
})
不过此时注意actions
中获取值需要解构才行
setStoreText ({ dispatch, commit }, {payload}) {
dispatch('setStoreData').then(() => {
console.log(222, payload)
commit('storeText', payload)
})
}
在actions可以dispatch
另一个异步的操作,也就是等一个任务完成了后,可以执行另一个commit
看到这里貌似这里有点想到,为啥所有的异步操作放在actions
里面了,mutation
只负责修改state
,所有异步操作产生的副作用的结果都统统交给了mutation
,这样很好保证devtool
了对数据的追踪。
总结
- 灵魂拷问,为什么会有
actions
中是异步,而mutations
是同步,从官方解释来看,修改state数据必须只能mutations
中修改,而假设mutions
内部有异步,那么会带来devtool
无法准确追踪state
变化,因为多个异步并不知道哪个异步会先执行完。但是话说回来,mutations
中有异步,依然可以修改state啊,因为业务中我并不太需要知道devtool
是如何追踪state
的变化,但是为了遵从规范,所有的异步都在actions
中处理,mutations
只集中干一件事,直接修改state
值 actions
是异步
操作的,actions
中可以有多个异步操作,但是最终的结果依然是交给mutations
去修改的,也就是说actions
中异步操作的副作用统一交给了mutations
去记录- 多个异步任务可以在
actions
中触发,dispatch('xxx')
返回的是一个Promise
- 本文code example[2]
参考资料
[1]vuex: https://v3.vuex.vuejs.org/zh/guide/mutations.html
[2]code example: https://github.com/maicFir/lessonNote/tree/master/vue/06-vuex-test
最后,看完觉得有收获的,点个赞,在看,转发,收藏等于学会,欢迎关注Web技术学苑,好好学习,天天向上!
相关文章
- js运行机制同步与异步(宏任务与微任务)
- openGL之API学习(六十九)水平同步 垂直同步「建议收藏」
- 一篇文章彻底搞懂异步,同步,setTimeout,Promise,async「建议收藏」
- 异步fifo与同步fifo_161是同步还是异步清零
- 【说站】java异步和同步的区别
- Django应用上线前有哪些注意事项?如何使用同步或异步容器启动Django应用?
- 面试官:react中的setState是同步的还是异步的
- React的useState和setState到底是同步还是异步呢?
- React 的 setState 同步还是异步
- 【Kotlin 协程】Flow 异步流 ① ( 以异步返回返回多个返回值 | 同步调用返回多个值的弊端 | 尝试在 sequence 中调用挂起函数返回多个返回值 | 协程中调用挂起函数返回集合 )
- SpringBoot中的定时任务的同步与异步你确定真的知道?
- 文件读写网络IO简单了解,同步IO和异步IO详解程序员
- IOS之同步请求、异步请求、GET请求、POST请求详解手机开发
- 说下Java中的同步块详解编程语言
- MySQL的异步与同步之比较(mysql异步同步)
- 同步Linux:持续更新最佳实践(linuxsync)
- 令人振奋的Oracle实时同步服务(oracle实时同步)
- 实战作业:实现基于分布式的LAMP架构,并将NFS实时同步到备份服务器
- Linux中的同步与异步:有着不同的处理方式(linux同步与异步)
- 探究Linux内核同步机制:保证系统稳定性的重要步骤(linux内核的同步)
- MongoDB订阅:保持数据同步的最佳解决方案(mongodb订阅)
- 局域网MSSQL同步实现远程数据共享(局域网 mssql 同步)
- SQL 同步MSSQL实现数据一致性(sql 同步mssql)
- Linux 进程间通信:实现安全的锁同步(linux 进程间 锁)
- Linux下共享内存实现同步运算(linux共享内存同步)
- 解决微服务间Redis同步的有效方式(微服务间的redis同步)
- MySQL的三种同步模式混合同步异步和半同步,了解这些模式有助于优化数据库性能
- 实现 mysql 主从同步不停机(mysql 不停机主从)
- Oracle CS锁基于资源的完全同步(oracle中的cs锁)
- Redis队列异步处理技术探索(redis队列同步处理)
- Redis实现同步读写锁保障事务安全性(redis读写同步锁)
- 红色虫蛀实现异步数据同步(redis蛀虫同步)
- 使用异步方式调用同步方法(实例详解)
- C#同步和异步调用方法实例
- 我的Node.js学习之路(三)--node.js作用、回调、同步和异步代码以及事件循环