说白了就是源码这样写的,这里再科普下WatchEffect
WatchEffect和Watch不同之处:
- 进入页面马上就回调用一下
- 有许多变体,WatchEffectSync等,都是WatchEffectOption下面的属性flush?: 'pre' | 'post' | 'sync';
当然可以帮你理解 watchEffect
的用法和场景。
场景描述
你提到的场景涉及到一个页码组件,用户可以点击页码来请求数据。如果用户快速点击多个页码,会导致多个异步请求并且可能出现数据错乱的问题。
问题分析
-
请求错乱:如果用户快速点击,从1到5连续请求,最终显示的内容可能不是用户想要的最后一页(例如第5页),而是第1页的响应最先返回,导致页面显示不准确。
-
带宽浪费:快速点击导致的多次请求,前几次的请求可能是用户并不关心的,造成了不必要的带宽浪费。
解决方案
为了处理这些问题,watchEffect
提供了一个 onInvalidate
的回调函数,可以用来取消之前的异步请求。
使用 watchEffect
下面是如何使用 watchEffect
和 onInvalidate
的示例代码:
import { ref, watchEffect } from 'vue';
const currentPage = ref(1);
watchEffect(onInvalidate => {
const token = performAsyncOperation(currentPage.value);
// 注册失效回调
onInvalidate(() => {
// 取消之前的请求
token.cancel();
});
});
function performAsyncOperation(page) {
// 这里是你异步请求的逻辑
const controller = new AbortController();
const signal = controller.signal;
fetch(`/api/data?page=${page}`, { signal })
.then(response => response.json())
.then(data => {
// 处理数据
});
return {
cancel: () => controller.abort() // 取消请求
};
}
解释
watchEffect
:当currentPage
变化时,它会重新执行传入的函数。onInvalidate
:每次watchEffect
被重新执行时,都会调用这个回调来清理之前的请求。token.cancel()
:通过调用这个方法来取消之前的请求,避免了不必要的带宽浪费和数据错乱。
总结
使用 watchEffect
和 onInvalidate
可以有效地管理异步请求,确保只有最新的请求被处理,避免了由于快速点击导致的请求错乱和资源浪费。这种方式使得你的组件更加高效和响应迅速。