首先讲讲版本问题,如果使用vue-cli2模版搭建的基础项目,注意,如果使用vue版本是2,当你你默认安装vuex肯定是4.x版本了,这里需要注意的是,你要降低vuex版本到3.x版本,不然store挂载不到vue上
【资料图】
当我们修改数据,只能通过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有多个异步的调用,你很难确定这些异步哪些先执行,很难追踪state的变化,所以也给调试带来了一定难度
话说回来,这么写也确实是可以做到更新state的值,如果我不用vuetool这个工具,貌似也没毛病
既然mutations是同步的事情,那么异步官方就使用了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了对数据的追踪。