vue keepalive,缓存

路由配置:

{
    path: '/submit',
    component: resolve => {
        require(['./pages/sb.vue'], resolve);
    },
    meta: {keepAlive: true}
},

app.vue配置

<!-- 这里是需要keepalive的 -->
<keep-alive>
    <router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>

<!-- 这里不会被keepalive -->
<router-view v-if="!$route.meta.keepAlive"></router-view>

(因为我的代码比较长,复制了下别人的,基本情况是一样的)
现在有这样一个情形:

list_1和list_2是由同一个vue页面渲染出来的两个路由页面;detail_1是list_1的详情页;
需要判断或者选择缓存的是list_1和list_2页面,详情页不进行缓存;

list_1--detail_1;
list_2--detail_2;

情形1:从list_1跳转到detail_1,缓存list_1页面;浏览器返回list_1,调用缓存;正常。

情形2:从list_1跳转到detail_1,缓存list_1页面;点击list_2,缓存list_2页面;再点击detail_2,浏览器返回list_2;此时页面显示的是list_1的数据,不正常。

情形2怎么处理?缓存了两个页面,无法选择或销毁想要的缓存页面。

阅读 4.4k
3 个回答

自己解决了,比较丑陋,体验不是很好。不过需求实现了。通过刷新list页面来清除不需要的缓存。

路由:

列表:
 {
                path: '/list_1',
                name: 'list_1',
                component: resolve => require(['pages/list'], resolve),
                meta: {
                    title: "列表1",
                    keepAlive: true,
                    isBack: false, //用于判断上一个页面是哪个
                    lastRoute: '',
                }
            }, {
               path: '/list_2',
                name: 'list_2',
                component: resolve => require(['pages/list'], resolve),
                meta: {
                    title: "列表2",
                    keepAlive: true,
                    isBack: false, //用于判断上一个页面是哪个
                    lastRoute: '',
                }
            }, 
详情:
 {
                            path: '/detail/:id',
                            name: 'detail',
                            component: resolve => require(['pages/detail'], resolve),
                            meta: {
                                title: "详情页",
                                keepAlive: false,
                                isBack: true, //用于判断上一个页面是哪个
                                lastRoute: '',
                            }
                        }, 

列表页主要代码:

watch: {
            '$route' (to, from) {
                //通过lastRoute来判断上一个页面是哪一个list页,通过isBack判断上一个页面是否是详情页
                if (from.meta.lastRoute !== to.name && from.meta.lastRoute && to.meta.isBack === false) {
                    this.$router.push({name:'reload'})
                }
            }
        },
      
        beforeRouteLeave(to, from, next) {
            //手动设置当前页的keepAlive=true
            from.meta.keepAlive = true
            //若果去的是列表页(isBack=false),销毁缓存
            if (to.meta.isBack === false){
                this.$destroy() //无法在beforeRouteEnter中使用
            }
            //在下一个页面的meta中设置lastRoute,以便在下一个页面中判断上一个页面的名字
            to.meta.lastRoute = this.$route.name
            next();
        },

详情页代码:

 beforeRouteLeave(to, from, next) {
            //在详情页判断上一个页面和下一个页面是否一致,一致则使用缓存,不一致则不使用缓存;
            //通过设置下一个页面(列表页)的keepAlive来确定是否使用;
            //因为列表页始终需要进行缓存,在这里(详情页)设置了他的keepAlive=false,所以需要在列表页重新设置keepAlive=rue
            if (from.meta.lastRoute !== to.name ){
                //若去的页面和来的页面不一致,销毁已经存在的list缓存
                to.meta.keepAlive = false;
            }
            next();
        },

按照我们团队的规范,list 列表页会进行 keep-alive 保持,详情页会在离开的时候直接 destroy,避免你提到的连续点开详情页的问题。因为一个component 只会初始化一次,在不销毁新建的情况下,可能无法触发数据的重新获取,进而展示上一次打开的detail_1,keep-alive 是直接休眠在唤醒。另外,针对数据可变的页面去做 keep-alive 也不太符合它的应用场景,既要它不变,又想它变,就矛盾了。

从l2进入d2,然后又回到列表页,显示的是l1,说明缓存没有成功,能把你列表页的代码贴出来看一下吗

另外,你一个组件加载不同的列表类型,是根据路由传参判断的类型吗,是不是返回列表页的时候参数没传过去,导致加载的是默认的列表页1?

又或者你是在一个页面加载了两个列表组件,只是用if或者show控制了他们的显示隐藏,从详情页回来的时候,该页面控制显示隐藏的变量重置了,所以显示的是默认的列表1?

不好猜!!!

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题