之前页面少的话 用keep-live结合router-view,使用keep-live的include属性就可以自己决定keep-live缓存那些组件不缓存那些组件,直到遇到个问题。
平时写的代码如下:
1 <router-view v-slot="{ Component, route }">
2
3 <keep-alive :include="\[...visitedViewPaths\]">
4
5 <component
6
7 :is="Component"/>
8
9 </keep-alive>
10
11 </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是相同的,这就不好处理了,想到的解决方案如下:
1 <router-view v-slot="{ Component, route }">
2
3 <keep-alive :include="\[...visitedViewPaths\]">
4
5 <component
6
7 :is="formatComponentInstance(Component,route)"/>
8
9 </keep-alive>
10
11 </router-view>
12
13 function formatComponentInstance(){
14 component.type = {
15 ...component.type,
16 name:route.path,
17 };
18 return component;
19 }
为什么要这么写,因为主要原因就是改个name的嘛,component.type放的是该组件对象,不能直接改,两个component.type所指向的对象是同一个,所以用一个新对象来。
以为解决了,结果报错,报啥错就不说了,我觉得应该是vue用那个弱引用map把组件对象当作key,存了一个其他数据,对象变了就取不到该数据了。
以为没法解决了,结果百度到了一个方法完美解决 https://blog.csdn.net/qq_42611074/article/details/127206469
思路还是一样,改组件name,这次不是改原组件name,直接新建一个组件出来,如下:
1<router-view v-slot="{ Component, route }">
2 <keep-alive :include="\[...visitedViewPaths\]">
3 <component
4 :is="formatComponentInstance(Component,route)"/>
5 </keep-alive>
6</router-view>
7
8const wrapperMap = new Map();
9
10function formatComponentInstance(component, route) {
11 let wrapper;
12 if (component) {
13 const wrapperName = route.path;
14 if (wrapperMap.has(wrapperName)) {
15 wrapper = wrapperMap.get(wrapperName);
16 } else {
17 wrapper = {
18 name: wrapperName,
19 render() {
20 return h(component);
21 },
22 };
23 wrapperMap.set(wrapperName, wrapper);
24 }
25 return h(wrapper);
26 }
27}
其中 visitedViewPaths 是你自己的需要缓存的name列表,现在组件名字由你控制了,就已经解决了
多谢原文章大佬,https://blog.csdn.net/qq_42611074/article/details/127206469
总算是解决了这个疑难问题哇