action 的用法
由于mutation不支持异步操作,所以vuex又提供了action,这个可以支持异步,在有些情况下就会非常方便。
异步操作分为两种情况,一个是内部的异步操作,一个是外部的异步操作。
比如访问后端API获取数据的时候,又或者把数据存入前端存储的时候。
我们先写个简单的例子
actions: {
// 异步获取数组
getArray(context) {
console.log('================================')
console.log('异步getArray——context', context)
setTimeout(() => {
context.commit('setArray', new Date().valueOf())
}, 1000)
},
// 异步获取数组
getArrayPromise(context) {
return new Promise((resolve, reject) => {
console.log('================================')
console.log('异步 getArrayPromise ——context', context)
setTimeout(() => {
const time = new Date().valueOf()
context.commit('setArray', time)
resolve(time)
}, 2000)
})
}
看看参数
011action的参数.png
-
内部的异步操作 getArray
获取数据后,通过commit改变状态,然后就完成了,简单方便。
缺点:调用者不知道啥时候加载完毕。 -
外部的异步操作 getArrayPromise
有的时候外部需要明确获知啥时候加载完成了,这样就需要返回一个promise。
我们new 一个 Promise就可以了,里面可以用axios等各种操作。
最后记得返回new出来的实例。
组件里的调用方法
// 异步操作
const actionManame = () => {
const store = Vuex.useStore()
const getArray = store.dispatch('getArray')
console.log('外部调用 getArray', getArray)
getArray.then((data) => {
console.log('===========')
console.log('getArray 异步操作完成,返回数据:', data)
console.log('===========')
})
const getArrayPromise = store.dispatch('getArrayPromise')
console.log('外部调用 getArrayPromise', getArrayPromise)
getArrayPromise.then((data) => {
console.log('===========')
console.log('getArrayPromise 异步操作完成,返回数据:', data)
console.log('===========')
})
return {
getArray,
getArrayPromise
}
}
如果不需要知道确定的完成时间的话,可以直接调用
store.dispatch('getArray')
如果要知道的话,可以写个then
store.dispatch('getArrayPromise').then((data) => {
console.log('异步操作完成,返回数据:', data)
})
这个用法和axios非常相似。
看看运行效果
012action的运行结果.png
虽然我们没有返回 promise实例的时候,外部也可以用then,但是这个是默认的,并不是我们真正执行操作后返回的。
我测试了一下,里面的 setTimeout 改成十秒,结果外面的then先执行了,十秒后内部操作完毕,外面没有任何反应。
所以外部调用,想要准确获知完成时间的话,还是要返回一个promise实例才行。
和axios配合使用
我们可以自己new 一个promise把axios包含进去,也可以直接返回axios的实例,比如这样
// axios,返回自己 的 new promise
getData(context) {
return new Promise((resolve, reject) => {
axios.get('demo.json')
.then((response) => {
const arr = response.data.company.formItem
console.log('getData - axios - response', response)
// context.commit('reloadArray', response.data.company.formItem)
resolve(arr)
})
.catch((error) => {
console.log('getData - axios - error', error)
})
})
},
// axios 返回 axios的promise
getData(context) {
const ajax = axios.get('demo.json')
ajax.then((response) => {
const arr = response.data.company.formItem
console.log('getData - axios - response', response)
// context.commit('reloadArray', response.data.company.formItem)
})
.catch((error) => {
console.log('getData - axios - error', error)
})
return ajax // 直接返回 axios 的promise的实例
}
调用方式
store.dispatch('getData').then((data) => {
console.log('===========')
console.log('getData 异步操作完成,返回数据:', data)
console.log('===========')
})
这样内部和外部都可以得到axios返回的数据。
013action的axios.png
如何选择就看对返回数据的封装程度了。
在线演示:
https://naturefwvue.github.io/nf-vue-cnd/cnd/project-vuex/
源码:
https://github.com/naturefwvue/nf-vue-cnd/tree/main/cnd/project-vuex
网友评论