作者:陈云杰
vue3 引入的 composition api 确实是一个质的飞跃,他完美的决绝了 vue 组件之间共享代码的问题,感谢 react 🤪
vueuse 是一套基于 composition api的函数库,可以理解成 vue 的 lodash,但是有时候很难知道哪些问题是vueuse里已经有解决方案了的,所以我想写一个系列,把平时用到的效果很好的 vueuse 方法记录下来。
今天我们就来看一下 computedAsync。
假设有一个这样的场景,用户可以在日历控件中点击不同的日期来查询当天的待办,想象一下该怎么实现这个需求:
const selectedDate = ref(new Date()); //用户选中的日期
我应该 watch selectedDate 这个变量,当他变化的时候通过api请求来拉取数据
watch(selectedDate, ()=>fetchTodos(...))
这样用户每点击一个日期,我们就会获取这个日期的待办数据。
我们已经实现了这个功能,但是不完美,想象一下如果用户非常快速的点击不同的日期(1,2,3,4日)会发生什么情况?
- 1号的数据可能会在切换到4号后才请求完毕,并显示在4号的列表里(请求先发先至),当然这个问题可以用其他方法解决
- 产生大量的 pending 请求,4号的数据要等前面的请求都结束才能正常返回(在弱网和http1下问题更严重)
所以需要一个方法来cancel掉旧的api请求,当我点击到4号的时候取消掉之前还没有结束的请求来节省资源。
vueuse 中的 computedAsync 完美的解决了这个问题
const todoList = computedAsync(
async onCancel => {
const abortController = new AbortController();
onCancel(() => abortController.abort());
const data = await fetchTodos(
selectedDate,
abortController.signal
);
return data;
},
[]
);
看名称就能知道他和 vue 内置的 computed 很像,只不过是一个异步的版本。
computedAsync在执行传入的callback时调用了selectedDate变量,selectedDate就会被收集成为一个依赖,当selectedDate变化的时候,callback就会被重新调用。
到目前为止他和 computed 还是一模一样的, 那么他和 computed 有哪些区别呢?
computedAsync的callback可以是异步的,例如发送http请求。computedAsync的callback有一个onCancel参数,用来取消之前还没有结束的异步callback。
我们来看一下效果,为了模拟弱网场景,我在devtool里设置了 低速3g
从动画里能看到当我点击一个新的日期时旧的请求就会被 cancel 掉,完美解决了问题 🎉