VUE3 动态缓存路由 keep-alive

1,889 阅读1分钟

项目有二级路由,即router-view中使用的页面还会有router-view。另外我们需要用到keep-alive进行页面级别的缓存,并且两层router-view都有用到,每个router-view的代码样式都如下

<router-view v-slot="{ Component }">
   <keep-alive>
      <component :is="Component" :key="$route.name" v-if="$route.meta.keepAlive"></component>
   </keep-alive>
   <component :is="Component" :key="$route.name" v-if="!$route.meta.keepAlive"></component>
</router-view>

遇到的问题

当子路由加载时,发现每个子页面里面onMounted钩子函数执行了两次

问题原因

经过排查后发现,其实根源在于最外层的那个router-view中使用了routenamemeta进行了判断,但这个route的name和meta进行了判断,但这个route并不符合预期。$route始终指向的是最外层的叶子节点路由,而我们在外层判断期望的则是一级目录的route,自然就会出问题。注意即使语法换成VueRouter4支持的v-slot="{ Component, route }",这里的route也依然有这个问题

解决办法

最直接的方式就是把router的层级都打平,自然就没有这个问题了,但这太low了,改造成本也不低。我的方案则是在外层router-view的时候,判断获取的route层级,如果不是一级目录则通过当前route获取后再使用,具体代码如下

<router-view v-slot="{ Component }">    <keep-alive>      <component :is="Component" :key="getFirstLevelRoute(route).name" v-if="$route.meta.keepAlive"/>    </keep-alive>    <component :is="Component" :key="getFirstLevelRoute(route).name" v-if="!$route.meta.keepAlive"/>  </router-view>

const getFirstLevelRoute =(route)=> {  if (!Array.isArray(route.matched) || route.matched.length === 0) {      return route;  }  return route.matched[0];}

原文地址