vue3,有个路由类似下面的结构,在 Layout 中,keepalive 根据 noCache 判断是否缓存。noCache: true 对 PaperDetail 是生效的,但返回 Paper 时,没有被缓存,导致会重新获取数据。 想达到的效果是:Paper 只在第一次进入时初始化,从 PaperDetail 返回时不会重新初始化。
{
  path: '/paper',
  name: 'Paper',
  component: Layout,
  children: [
    {
      path: '',
      name: 'Paper',
      component: () => import('@/views/paper/index.vue'),
      meta: {
        title: 'paper',
      },
    },
    {
      path: ':id',
      name: 'PaperDetail',
      component: () => import('@/views/paper-detail/index.vue'),
      meta: {
        title: 'paperDetail',
        noCache: true,
      },
    },
  ],
},
换成这样可以了,只不过不能包在 transition 里
<router-view v-slot="{ Component, route }">
  <keep-alive>
    <component :is="Component" v-if="!route.meta.noCache" :key="route.name" />
  </keep-alive>
  <component :is="Component" v-if="route.meta.noCache" :key="route.name" />
</router-view>
|  |      1christin      2021-05-17 17:26:53 +08:00 via iPhone 直接用 keepalive 包裹 paper 就能得到你要的效果啊 为什么要加判断? 把使用组件的代码也贴一下吧 | 
|      2cw2k13as      2021-05-17 17:39:53 +08:00 你这样不行好像,只能操作 keep 的 include 和 exclude,好几年没写过了,我记得好像在 routerbefore,next 之前更改都无效下一次才生效,你自己研究下 | 
|  |      3gzf6 OP @christin 大概像这样 ``` <router-view v-slot="{ Component, route }"> <transition :name="route.meta.transition || 'fade-transform'" mode="out-in"> <keep-alive v-if="!route.meta.noCache"> <component :is="Component" /> </keep-alive> <component :is="Component" v-else /> </transition> </router-view> ``` | 
|      4faceRollingKB      2021-05-17 17:56:10 +08:00 export function CreateKeepAliveRouter(cacheRouters, noCacheRouters = []) { if(GetJsType(cacheRouters) !== 'Array') { cacheRouters = [cacheRouters] } if(GetJsType(noCacheRouters) !== 'Array') { noCacheRouters = [noCacheRouters] } return { path: '', component: { render(h) { return h('keep-alive', {}, [ h('router-view') ]) } }, children: [ ...cacheRouters, { path: '', component: { data() { return { show: null } }, activated() { this.show = false this.$nextTick(() => { if (this.show === false) { this.show = true } }) }, deactivated() { this.show = null }, render(h) { if (this.show) { return h('router-view') } else { return '' } } }, children: [ ...noCacheRouters ] } ] } } // 用法 routers = [ {...}, // 路由 1 CreateKeepAliveRouter([ {...}, // 路由 2 ], [ {...}, // 路由 3 ]) ] 效果: 1 、只有路由 2 有缓存效果 2 、路由 2 --> 路由 1 --> 路由 2,缓存消失 3 、路由 2 --> 路由 3 --> 路由 2,缓存不消失 | 
|      5faceRollingKB      2021-05-17 17:57:08 +08:00 // export type JsType = 'Array' | 'String' | 'Symbol' | 'Number' | 'Null' | 'Undefined' | 'Object' | 'RegExp' | 'Date' | 'Boolean' | 'HTMLAnchorElement' | string; export function GetJsType(val) { return Object.prototype.toString.apply(val).match(/\[object\s([a-zA-Z]+)\]/)[1]; } | 
|  |      6sujin190      2021-05-17 18:00:39 +08:00 <keep-alive> <router-view v-if="!route.meta.noCache" /> </keep-alive> <router-view v-if="route.meta.noCache" /> 似乎应该这样写吧,似乎 keep-alive 底层的组件缓存是放在当前实例上的,不是全局缓存,if 放在 keep-alive 组件上的话如果导致组件重建似乎在实例上的组件缓存也消失了吧,下一个进来整个页面肯定要重新渲染了 | 
|  |      7OHyn      2021-05-17 18:54:27 +08:00 | 
|  |      8christin      2021-05-17 19:25:20 +08:00 via iPhone @gzf6 感觉这样用 v-if 判断有点问题 假设第一次 v-if 命中 keep-alive 渲染了 然后你跳转到 paperdetail keep-alive 又没有命中 导致不渲染 这样来回跳转 keep-alive 是一直在渲染和取消渲染 |