Closed okjesse closed 7 years ago
@leixu2txtek 我已经放弃了那个PR,通过强行清除缓存的方法,我变相得实现了动态删除缓存组件的功能。 我目前全站使用缓存,通过拦截页面离开的路由事件来根据业务逻辑实现删除缓存的功能,以下代码片段供参考:
- 将router-view放到keep-alive中,默认全站默认使用缓存。
<keep-alive><router-view class="transit-view"></router-view></keep-alive>
- 我在routes里将所有的页面进行了分层。如meta.rank代表页面层次,如1.5>2.5>3.5意味着从第一层进入第二层进入第三层页面。
routes: [ { path: '/', redirect:'/yingshou', }, { path: '/yingshou', meta:{rank:1.5,isShowFooter:true}, }, { path: '/contract_list', meta:{rank:1.5,isShowFooter:true}, }, { path: '/customer', meta:{rank:1.5,isShowFooter:true}, }, { path: '/wode', meta:{rank:1.5,isShowFooter:true}, }, { path: '/yingfu', meta:{rank:1.5,isShowFooter:true}, }, { path: '/yingfu/pact_list', meta:{rank:2.5}, }, { path: '/yingfu/pact_detail', meta:{rank:3.5}, }, { path: '/yingfu/expend_view', meta:{rank:4.5}, }, { path: '/yingfu/jizhichu', meta:{rank:5.5}, }, { path: '/yingfu/select_pact', meta:{rank:6.5}, }, { path: '/yingfu/jiyingfu', meta:{rank:7.5}, }, ]
复制到剪切板
- 因为所有页面都会缓存,所以核心思路是【何时销毁缓存?】。我的设计是:同层级页面切换或进入下一层页面都会保留当前页缓存,【返回上一层页面时则销毁当前页面缓存】。
- 所以我在main.js里,使用Vue.mixin的方法拦截了路由离开事件,并在该拦截方法中实现了销毁页面缓存的功能。核心代码如下:
Vue.mixin({ beforeRouteLeave:function(to, from, next){ if (from && from.meta.rank && to.meta.rank && from.meta.rank>to.meta.rank) {//如果返回上一层,则摧毁本层缓存。 if (this.$vnode && this.$vnode.data.keepAlive) { if (this.$vnode.parent && this.$vnode.parent.componentInstance && this.$vnode.parent.componentInstance.cache) { if (this.$vnode.componentOptions) { var key = this.$vnode.key == null ? this.$vnode.componentOptions.Ctor.cid + (this.$vnode.componentOptions.tag ? `::${this.$vnode.componentOptions.tag}` : '') : this.$vnode.key; var cache = this.$vnode.parent.componentInstance.cache; var keys = this.$vnode.parent.componentInstance.keys; if (cache[key]) { if (keys.length) { var index = keys.indexOf(key); if (index > -1) { keys.splice(index, 1); } } delete cache[key]; } } } } this.$destroy(); } next(); }, });
复制到剪切板 总结:其实就是通过页面组件所在的上层keepAlive组件,暴力操控该对象中的cache列表。。。 简单又直接,虽然不是很优雅,然而很好用,哈哈:) 当然还是希望官方能支持API出来更好。
但是这样内存还是不会释放,我关掉keepalive就没事,加上keepalive然后手动移除缓存并销毁内存还是一直在上涨,不知道有没有关注这方面?
我也发现了这个问题,在论坛上提了个问 https://forum.vuejs.org/t/keepalive/109030 不知道有没有大佬能解答一下。。。
我这里的场景是点击导航的时候不缓存,但是页面提供了一个返回上级页面,这时取缓存;且详情页返回到列表页也取缓存,目前是实现了需求。
const cacheThis = new Map();
Vue.mixin({
async beforeRouteLeave(to, from, next) {
const isNavClick = (await sessionStorage.getItem('isNavClick')) === '1'
if (isNavClick) {
if (cacheThis.has(to.name)) {
cacheThis.get(to.name).$destroy()
} else {
cacheThis.set(from.name, this)
}
}
sessionStorage.setItem('isNavClick', '0');
next()
}
})
原理就是通过mixin混入一个组件内路由跳转前的守卫,缓存当前组件的this实例到一个map对象里,当点击导航的时候获取一下是否缓存了当前要去的这个实例,如果有,则调用这个实例的destory销毁缓存,达到重新渲染的目的。其他的情况都取keep-alive缓存。
讨论了快4年了,这个问题还没解决啊???比较明显的一个问题是 keep-alive 应该缺少两个必不可少的配套方法:clear 方法用来清空 keep-alive 实例所属的所有已缓存组件或页面;remove() 方法用来移除 keep-alive 实例所属的某个已缓存组件或页面;
暴力操作 keys 和 cache,并用 $destroy 销毁实例,很好用。
希望官方打开并解决,确实有问题! “多个路由对应一个组件” 这不是include能解决的事
How can i destory the component cache by myself ?
In this way ! @elewen @zero7u
<!-- Tabs.vue -->
<template>
<router-link>
Tab A
<span @click.prevent.stop="closeSelectedTag(tag)" />
</router-link>
</template>
<script>
export default {
computed: {
cache: {
get() {
if (!this.$route.matched[1]) return
const instances = this.$route.matched[1].instances;
return instances.default.$vnode.parent.componentInstance.cache;
},
set(val) {
this.$route.matched[1].instances.default.$vnode.parent.componentInstance.cache = val
}
}
},
methods: {
closeSelectedTag(view) {
// Remove selected tag
// ...
// Remove the cache from cache
const cache = this.cache;
const str = RegExp('.*' + view.fullPath);
let key = '';
Object.keys(cache).forEach(el => {
if (str.test(el)) {
key = el;
}
});
delete cache[key];
}
}
}
</script>
讨论了快4年了,这个问题还没解决啊???比较明显的一个问题是 keep-alive 应该缺少两个必不可少的配套方法:clear 方法用来清空 keep-alive 实例所属的所有已缓存组件或页面;remove() 方法用来移除 keep-alive 实例所属的某个已缓存组件或页面;
不能赞同更多
Custom cache strategy and matching rules for KeepAlive https://github.com/vuejs/rfcs/pull/284
@jkzing 如果我同一个组件加载了两次,一个需要缓存,一个不需要缓存怎么弄,他们的组件name是一样的呀
我也是这个疑问,include无法满足这个需求,多个路由页面对应一个组建,那就只有一个组件name,咋办?
自己实现一个keep-alive组件替换vue的keep-alive,这篇知乎文章有介绍:https://zhuanlan.zhihu.com/p/269385782,但是需要自己将keep-alive的缓存key从name修改成根据路径path进行缓存。
@zhangchugao 你好,你发的链接好像失效了,能再贴一下吗,谢谢
@zhangchugao 你好,你发的链接好像失效了,能再贴一下吗,谢谢
@zhangchugao 你好,你的解决方案非常好,和我的问题一模一样。但是有个小小问题,路由名字也是一样的。路由地址也是一样的,但是参数不一样,两个页面的,分别缓存起来。
例如: http://localhost/#/ehr/parameter/index/3 http://localhost/#/ehr/parameter/index/13
路由信息:
{
path: "/ehr/parameter",
component: Layout,
hidden: true,
children: [
{
path: "index/:wid(\\d+)",
component: resolve =>
require(["@/views/datamodel/winparameter/index"], resolve),
name: "WinParameter",
meta: { title: "加载参数", activeMenu: "/datamodel/winparameter" }
}
]
}
标签卡的组件页面,全部都空白页面了
@zhangchugao 你好,你的解决方案非常好,和我的问题一模一样。但是有个小小问题,路由名字也是一样的。路由地址也是一样的,但是参数不一样,两个页面的,分别缓存起来。
例如: http://localhost/#/ehr/parameter/index/3 http://localhost/#/ehr/parameter/index/13
路由信息:
{ path: "/ehr/parameter", component: Layout, hidden: true, children: [ { path: "index/:wid(\\d+)", component: resolve => require(["@/views/datamodel/winparameter/index"], resolve), name: "WinParameter", meta: { title: "加载参数", activeMenu: "/datamodel/winparameter" } } ] }
标签卡的组件页面,全部都空白页面了
你好,我这边测试了,发现没有问题,请问你是否修改了自定义keep-alive组件js的缓存key从name修改为更具path路径缓存,原作者贴的代码当中使用的组件的name来缓存对应的每个路由的。我修改如下图所示: 你可以查看你是否修改了图片中的代码。
@zhangchugao 你好,你的解决方案非常好,和我的问题一模一样。但是有个小小问题,路由名字也是一样的。路由地址也是一样的,但是参数不一样,两个页面的,分别缓存起来。 例如: http://localhost/#/ehr/parameter/index/3 http://localhost/#/ehr/parameter/index/13 路由信息:
{ path: "/ehr/parameter", component: Layout, hidden: true, children: [ { path: "index/:wid(\\d+)", component: resolve => require(["@/views/datamodel/winparameter/index"], resolve), name: "WinParameter", meta: { title: "加载参数", activeMenu: "/datamodel/winparameter" } } ] }
标签卡的组件页面,全部都空白页面了
你好,我这边测试了,发现没有问题,请问你是否修改了自定义keep-alive组件js的缓存key从name修改为更具path路径缓存,原作者贴的代码当中使用的组件的name来缓存对应的每个路由的。我修改如下图所示: 你可以查看你是否修改了图片中的代码。
是的,我刚刚改好了,vue2测试了,有vue3版本的吗?官方一直不处理这个问题,郁闷。
@zhangchugao 你好,你的解决方案非常好,和我的问题一模一样。但是有个小小问题,路由名字也是一样的。路由地址也是一样的,但是参数不一样,两个页面的,分别缓存起来。 例如: http://localhost/#/ehr/parameter/index/3 http://localhost/#/ehr/parameter/index/13 路由信息:
{ path: "/ehr/parameter", component: Layout, hidden: true, children: [ { path: "index/:wid(\\d+)", component: resolve => require(["@/views/datamodel/winparameter/index"], resolve), name: "WinParameter", meta: { title: "加载参数", activeMenu: "/datamodel/winparameter" } } ] }
标签卡的组件页面,全部都空白页面了
你好,我这边测试了,发现没有问题,请问你是否修改了自定义keep-alive组件js的缓存key从name修改为更具path路径缓存,原作者贴的代码当中使用的组件的name来缓存对应的每个路由的。我修改如下图所示: 你可以查看你是否修改了图片中的代码。
是的,我刚刚改好了,vue2测试了,有vue3版本的吗?官方一直不处理这个问题,郁闷。 不好意思,暂时没有,你可以自己尝试。
这是来自QQ邮箱的假期自动回复邮件。 您好,我现在没在上网,无法亲自回复您的邮件。我会在上网后,尽快给您回复。
真的服了,到现在还不能手动清keepalive?vue3又把$destroy去了,嘛呢,开倒车呢?
What problem does this feature solve?
我在使用vue做单页应用时,在多个功能切换的时候,希望能达到动态创建tab进行切换的效果,和以前使用iframe一样,这些tab是keep-alive的,但如果太多keep-alive的时候,浏览器内存占用会过大。我希望能够达到可切换的tab最多例如只有十个,前面的我会用程序自动关闭对应tab,此时希望能把其缓存的组件也对应清除。
What does the proposed API look like?
例如:vm.$clearKeepAlived(routerName)