重复使用一个路由组件而不同路径遇到的周期函数触发问题


最近在开发时,遇到开发相同的页面,很多函数和布局也大差不多,所以在路由注册时就给它们分配了不同的 path,通过一些判断走不同的逻辑去获取数据。

此时,路由组件包裹了一个 KeepAlive,让他们保持不被销毁。

下面是路由注册情况:

const routes = [
  {
    name: RouteName.HOME,
    path: "/",
    component: () => import("./fragments/Common.vue")
  },
  {
    name: RouteName.CATEGORY,
    path: "/c/:id/:page",
    component: () => import("./fragments/Common.vue")
  }
];

这两个 path 对应的都是同一个组件,由于 KeepAlive 的作用,当从一个 path 跳转到 Common.vue 之后,再从另一个 path 跳转到同一个 Common.vue,此时第二次再进入这个 Common.vue 之后,它还是保持上一次的状态。这是因为 KeepAlive 导致的。所以,谁先执行谁就先执行对应的逻辑,下次以不同的 path 进入到路由组件之后都不会执行下次或下下次进入的逻辑,除非强制性刷新浏览器。

下面是 Common.vue setup 函数中的代码,fetchData 是获取数据的,是一个异步函数。根据是否传递参数而执行不同的获取数据 API。

if (categoryId) {
  fetchData(categoryId, categoryPage, true);
} else {
  fetchData(false, 1, false);
}

来看看组件的周期到底是怎么样的?

这是第一次进入的 path:

这是第二次进入的 path:

下面是进入不同 path 而是同一个路由组件的生命周期函数触发情况:

可以看到,Common.vue 路由组件发生了很多次 activated 和 deactived。唯独 mounted 这类周期函数只触发了一次,也就是第一次进入这个路由组件时触发的。

那么,去掉 KeepAlive 是否可以?答案,是可以的。但,这破坏了我最开始的业务要求,即缓存组件状态,而不希望切换时销毁路由组件。

不去掉 KeepAlive 是否也可以?答案,也是可以的。解决办法是使用 KeepAlive 的周期函数:activated 或 deactived。具体说明请查看官方文档??:KeepAlive 缓存实例的生命周期。