Vue3 - watch 监听路由状态变化切换下一个页面 watch 函数还在执行

发布时间 2023-10-13 17:50:55作者: Himmelbleu

描述

你可能会通过 watch 函数监听路由变化,当路由参数发生变化之后,重新调用 fetchData 获取数据渲染页面。即,同路由页面切换。

但是,遇到了 A 页面切换到 B 页面时,A 页面的 watch 会被触发,导致报错。这是因为进入其他页面之前,你没有清除这个 watch 监听。

虽然随着组件消失而自动清除 watch,但是遇到现在这个情况就需要在什么时候我们手动清除它。

清除 watch

你可以在进入其他路由组件之前清除它,幸运的是,vue-router 提供了这一函数:onBeforeRouteLeave

file:[结合 onBeforeRouteLeave 清除 watch]
const route = useRoute();

const clearWatcher = watch(route, async (to, from) => {
  await fetchData(to.params.id);
});

onBeforeRouteLeave(() => {
  clearWatcher();
});

onUnmounted(() => {
  clearWatcher();
});

await fetchData(route.params.id);

根据官方文档的说法,watch 默认是懒侦听的,即仅在侦听源发生变化时才执行回调函数。如果我没理解错的话,这就是如上诉所描述中那样,进入 B 页面之后,由于 route 数据源发生变化,里面的回调函数被执行,但是 watch 本身确实被清除,但是回调函数还在。

文档中也提供了如何清除副作用的方法,过程可能比较麻烦,但下面还有更简单的做法。

取消 watch 监听参数变化

那就是调用 onBeforeRouteUpdate 函数,这个是可以知道路由参数变化的函数,里面传递回调执行我们重新获取数据的异步就行。这个我测试过,进入其他页面,不会执行它的回调,也就不会报错了,而且这种方式简单。

file:[使用 onBeforeRouteUpdate 监听路由参数变化]
const route = useRoute();

onBeforeRouteUpdate(async updateGuard => {
  await fetchData(updateGuard.params.id);
});

await fetchData(route.params.id);