V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
gzf6
V2EX  ›  Vue.js

请教, vue3 中的 keepalive 与路由结构

  •  
  •   gzf6 · 2021-05-17 16:12:41 +08:00 · 2696 次点击
    这是一个创建于 1284 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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,
          },
        },
      ],
    },
    
    第 1 条附言  ·  2021-05-17 20:13:44 +08:00

    换成这样可以了,只不过不能包在 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>
    
    8 条回复    2021-05-17 19:25:20 +08:00
    christin
        1
    christin  
       2021-05-17 17:26:53 +08:00 via iPhone
    直接用 keepalive 包裹 paper 就能得到你要的效果啊 为什么要加判断?
    把使用组件的代码也贴一下吧
    cw2k13as
        2
    cw2k13as  
       2021-05-17 17:39:53 +08:00
    你这样不行好像,只能操作 keep 的 include 和 exclude,好几年没写过了,我记得好像在 routerbefore,next 之前更改都无效下一次才生效,你自己研究下
    gzf6
        3
    gzf6  
    OP
       2021-05-17 17:50:00 +08:00
    @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>
    ```
    faceRollingKB
        4
    faceRollingKB  
       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,缓存不消失
    faceRollingKB
        5
    faceRollingKB  
       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];
    }
    sujin190
        6
    sujin190  
       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 组件上的话如果导致组件重建似乎在实例上的组件缓存也消失了吧,下一个进来整个页面肯定要重新渲染了
    OHyn
        7
    OHyn  
       2021-05-17 18:54:27 +08:00
    christin
        8
    christin  
       2021-05-17 19:25:20 +08:00 via iPhone
    @gzf6 感觉这样用 v-if 判断有点问题 假设第一次 v-if 命中 keep-alive 渲染了 然后你跳转到 paperdetail keep-alive 又没有命中 导致不渲染
    这样来回跳转 keep-alive 是一直在渲染和取消渲染
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1218 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 23:13 · PVG 07:13 · LAX 15:13 · JFK 18:13
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.