完美解决vue3 keep-alive多个路由使用同一个组件的缓存问题

14 篇文章 0 订阅

之前页面少的话 用keep-live结合router-view,使用keep-live的include属性就可以自己决定keep-live缓存那些组件不缓存那些组件,直到遇到个问题。

平时写的代码如下:

    <router-view v-slot="{ Component, route }">

        <keep-alive :include="[...visitedViewPaths]">

            <component 

              :is="Component"/>

        </keep-alive>

    </router-view>

其中 visitedViewPaths表示的是一个放Component name的数组,可以去看文档 https://cn.vuejs.org/guide/built-ins/keep-alive.html#include-exclude

如果配置的路由A用A组件,路由B用A组件,因为include属性是靠组件的name来决定缓存与不缓存的,还有这种情况,路由里配置的{ path: ‘/users/:id’, component: User },这样的配置也是多个路由使用同一个组件的情况,现在这种路由对应的组件实例name是相同的,这就不好处理了,想到的解决方案如下:

    <router-view v-slot="{ Component, route }">

        <keep-alive :include="[...visitedViewPaths]">

            <component 

              :is="formatComponentInstance(Component,route)"/>

        </keep-alive>

    </router-view>
    
    function formatComponentInstance(){
        component.type = {
            ...component.type,
            name:route.path,
        };
        return component;
    }

为什么要这么写,因为主要原因就是改个name的嘛,component.type放的是该组件对象,不能直接改,两个component.type所指向的对象是同一个,所以用一个新对象来。
以为解决了,结果报错,报啥错就不说了,我觉得应该是vue用那个弱引用map把组件对象当作key,存了一个其他数据,对象变了就取不到该数据了。
以为没法解决了,结果百度到了一个方法完美解决 https://blog.csdn.net/qq_42611074/article/details/127206469

思路还是一样,改组件name,这次不是改原组件name,直接新建一个组件出来,如下:

<router-view v-slot="{ Component, route }">
    <keep-alive :include="[...visitedViewPaths]">
        <component 
            :is="formatComponentInstance(Component,route)"/>
    </keep-alive>
</router-view>

// 用来存已经创建的组件
const wrapperMap = new Map();
// 将router传个我们的组件重新换一个新的组件,原组件包里面
function formatComponentInstance(component, route) {
    let wrapper;
    if (component) {
        const wrapperName = route.path;
        if (wrapperMap.has(wrapperName)) {
            wrapper = wrapperMap.get(wrapperName);
        } else {
            wrapper = {
                name: wrapperName,
                render() {
                    return h(component);
                },
            };
            wrapperMap.set(wrapperName, wrapper);
        }
        return h(wrapper);
    }
}

其中 visitedViewPaths 是你自己的需要缓存的name列表,现在组件名字由你控制了,就已经解决了
多谢原文章大佬,https://blog.csdn.net/qq_42611074/article/details/127206469
总算是解决了这个疑难问题哇

DEMO,代码开源

  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值