New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
希望keep-alive能增加可以动态删除已缓存组件的功能 #6509
Comments
其实这个问题之前在forum上回答过一次,这件事可以用 给你写个简单的例子: |
isn't this a dup of #6259 ? |
@posva Yes, similar situation. It's about to dynamically clear |
@jkzing 非常感谢,我上面说的场景您的方法应该可以完成,但我还有个场景,例如列表页面,如果是从tab切换过来的时候,希望是keep-alive,直接从内存拿数据,如果是修改一条数据后,程序跳转到列表页面,希望是能够后台获取新的数据,虽然我可以页面完成后再从后台获取,但感觉不够优雅,如果有上述api,我只需要在修改后把这个router的keep-alive清除,数据应该就会自动从后台获取了。不知道我表述的是否能够让您明白,总之,我希望能够优雅的把单页应用做成和以前iframe的多tab效果一样: http://www.sucaihuo.com/modals/16/1653/demo/ 以上,谢谢。 |
@okjesse 这个也是可以做到的,你需要的只是把 总之,vue提供了基础的API来完成这件事,想方便地用起来的话需要稍微封装下。 |
@jkzing 明白,谢谢了,我现在是自己写了个keep-alive实现的,我试试 按照您的方法 |
@jkzing ,不过就算这样能够实现,我觉得最好还是得有个这个api,语义会不太一样,我所希望的是清除已经keep-alive的数据,组件本身还是alive的,而不是不停的切换是否会alive |
这只是其中一个问题,我们遇到的不停开新页面,会导致内存过大,最后浏览器卡死的问题,应该和keepalive无关。如果可以,我们重现个现象给@jkzing看 |
我们要实现的是,在跳转到页面的前一刻才决定是否用缓存的页面,还是新页面。老的api做不到的吧 |
我目前也遇到了这个需求,再菜单列表点击连接,在tabs里面增加一个标签并缓存新开的组件;点击关闭标签我希望能删除缓存的组件;我是在组件里面deactivated钩子函数调用this.$destroy();这样能清除缓存,但是发现下次打开这个连接的时候,新的组件不会被缓存了 |
@fadexiii 现有的方法我解决了,通过动态设置includes,可以实现 |
@okjesse 我的keep-alive 里面包含的是一个 |
@okjesse 刚刚是我没有定义conponent的name属性,定义之后可以了,多谢 |
FYI: implemented in 2cba6d4 |
@fadexiii #6961 和你一样的需求,请问下你们怎么解决的呀 |
@Jack-93 利用keep-alive的include,新打开标签时,把当前组件名加入到include数组里,关闭标签时从数组中删除关闭标签的组件名就可以了 |
看到$destroy这个方法,我觉得这就是正确的用法,通过组件里不同的用户行为决定离开页面时是否缓存组件。 |
@wanyaxing 我也遇到过你类似的问题 |
@realfly08 我尝试提交了一个PR去解决这个问题,不过好像提交失败了,我没搞清楚怎么通过vue的自动代码审查-。- #7151 我之前也是准备全站缓存,然后碰到了缓存更新的逻辑大坑。 |
@wanyaxing 我也遇到了类似的问题,要实现的逻辑功能,A->B->C 3个页面, 返回的时候使用缓存,再次进入的时候重新渲染,目前是每个页面都keep alive, 然后我在B页面进行判断如果是返回上一级页面(go -1)就在deactivated中销毁当前组件,调用$destroy,当按顺序再次进入到C页面,返回到B页面,可以看到又重新创建了B页面,同时缓存中还存在着一个B页面 |
@fadexiii keep-alive 配合router-view怎么用?
includes 写的是路由配置中的name: 'login'
为什么我把 includes 赋值为空字符串,依然可以缓存?我的需求就是需要手动销毁缓存的路由 |
在组件被销毁之后,缓存并没有被清空掉,我觉得问题是在这里。 @wanyaxing 看了你提交的PR ,应该是有效的,或者开放一个 remove cache 的API 也行的吧 |
@leixu2txtek 我已经放弃了那个PR,通过强行清除缓存的方法,我变相得实现了动态删除缓存组件的功能。 我目前全站使用缓存,通过拦截页面离开的路由事件来根据业务逻辑实现删除缓存的功能,以下代码片段供参考:
总结:其实就是通过页面组件所在的上层keepAlive组件,暴力操控该对象中的cache列表。。。 简单又直接,虽然不是很优雅,然而很好用,哈哈:) 当然还是希望官方能支持API出来更好。 |
@wanyaxing 我是通过路由来控制页面的缓存 比如,我有 /executed/,以及他的子路由 /executed/chart/ ,我同样是用 mixin 方法hack 路由离开时候 销毁不需要缓存的组件,我要做到的是从父级到子集路由,父级被缓存,其他情况都被销毁,这样我们只要控制路由就行了,不用增加任何的属性什么的,我比较懒; // 支持页面保持
Vue.mixin({
beforeRouteLeave(to, from, next) {
if (!to.path.startsWith(from.path)) this.$destroy();
next();
}
}); @wanyaxing 谢谢,你的代码对我非常有用。我参考一下; 我发现确实是缓存没有被销毁导致的。尽力在和 @LinusBorg 沟通 |
@heng1234 你好你这个问题解决了吗,哪位这个问题可以留个联系方式指导一下吗 |
不要用路由切换页面 用组件的方式切换
这篇博客仅供参考 我是用组件切换的方式的 不是用这种
https://blog.csdn.net/qq_39313596/article/details/82628953
xiaoluoheng@foxmail.com
发件人: Codezero123
发送时间: 2019-12-03 10:04
收件人: vuejs/vue
抄送: hlvy; Mention
主题: Re: [vuejs/vue] 希望keep-alive能增加可以动态删除已缓存组件的功能 (#6509)
tab切换的时候缓存 关闭缓存要销毁及下次打开重新加载 多重嵌套子路由页面也是
@heng1234 你好你这个问题解决了吗
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
@wanyaxing 你这种对于三级路由缓存不起效,比如vue-element-admin里面,开启多个三级tag标签的时候,切换tag标签不会销毁缓存组件,但是只开启一个三级路由tag标签,是可以销毁的。比如开启下面的menu1-0 和menu1-1。 `Vue.mixin({
}, |
思路就是这么个思路,思路是没有问题的,具体何时调用何时销毁缓存,得看你业务中具体实现。 |
我们业务这边这种场景应该很场景吧: 现在发现到2的时候无法清除所有缓存,把keep-alive的max值放到了vuex并设置为了1还是无效,看vue开发者工具里还是有缓存页面的。 |
你这种场景里啊,在2的时候,应该考虑直接刷新页面,是最保险也最直接的方案。 |
因为includes对应的是组件的name,如果多个路由对应一个组件,怎么办呢?有什么办法可以给同一个组件命不同的名字吗? |
目前来看这是最好的解决方法. 尤其是需要打开多个同组件不同参数的标签页时. |
我也发现了这个问题,在论坛上提了个问 |
我这里的场景是点击导航的时候不缓存,但是页面提供了一个返回上级页面,这时取缓存;且详情页返回到列表页也取缓存,目前是实现了需求。 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()
}
})
|
讨论了快4年了,这个问题还没解决啊???比较明显的一个问题是 keep-alive 应该缺少两个必不可少的配套方法:clear 方法用来清空 keep-alive 实例所属的所有已缓存组件或页面;remove() 方法用来移除 keep-alive 实例所属的某个已缓存组件或页面; |
暴力操作 keys 和 cache,并用 $destroy 销毁实例,很好用。 |
希望官方打开并解决,确实有问题! |
<!-- 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> |
不能赞同更多 |
Custom cache strategy and matching rules for KeepAlive vuejs/rfcs#284 |
自己实现一个keep-alive组件替换vue的keep-alive,这篇知乎文章有介绍:https://zhuanlan.zhihu.com/p/269385782,但是需要自己将keep-alive的缓存key从name修改成根据路径path进行缓存。 |
@zhangchugao 你好,你发的链接好像失效了,能再贴一下吗,谢谢 |
|
@zhangchugao 你好,你的解决方案非常好,和我的问题一模一样。但是有个小小问题,路由名字也是一样的。路由地址也是一样的,但是参数不一样,两个页面的,分别缓存起来。 例如: 路由信息: {
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)
The text was updated successfully, but these errors were encountered: