keep-alive vnode缓存与shapeFlag不一致导致组件切换路由被销毁的问题
Version
3.2.26
Reproduction link
Steps to reproduce
<router-view v-slot="{ Component }">
<transition name="fade-transform" mode="out-in">
<keep-alive :include="cachedViews">
<component :is="Component" />
</keep-alive>
</transition>
</router-view>
重现
- 初始状态cachedViews为[]
- component mounted之后,改变cachedViews的值,使component命中cachedViews,component的vnode会被缓存到 cache中,但是返回的vnode的shapeFlag是4,没有被标记为COMPONENT_SHOULD_KEEP_ALIVE(260)
- 切换路由,component被销毁,isUnmounted: true
- 再次切换回路由回来,会命中keep-alive的缓存,返回缓存的vnode,由于vnode对应的组件被销毁,导致组件会假死失去响应。
可能原因
// 289行
// 当组件mounted之后update就会将vnode拷贝一份
// clone vnode if it's reused because we are going to mutate it
if (vnode.el) {
vnode = cloneVNode(vnode)
if (rawVNode.shapeFlag & ShapeFlags.SUSPENSE) {
rawVNode.ssContent = vnode
}
}
// 322行
// 改变了拷贝的vnode的shapeFlag为KEEP_ALIVE,但是返回的是rawVNode
// rawVNode的shapeFlag还是4
// avoid vnode being unmounted
vnode.shapeFlag |= ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE
current = vnode
return rawVNode
What is expected?
组件mounted之后命中include能正确被缓存。
What is actually happening?
组件mounted之后命中include能被缓存,切换路由时组件会被销毁,重新激活时组件假死。
maybe it's a duplicate of https://github.com/vuejs/vue-next/issues/4984 /cc @ygj6
@edison1105 确实和 #4984 差不多的问题,用你的方法解决了,感谢!
<script lang="ts">
import { defineComponent,computed } from 'vue'
import { useStore } from 'vuex'
export default defineComponent({
name: 'AppMain',
setup() {
const store = useStore();
const cachedViews = computed(() => [...store.getters.cachedViews])
return {
cachedViews
}
},
})
</script>
展开数组后transition组件能响应数组项变化了,当cacheViews push、splice时 ,update从keep-alive组件提升到了transition组件,从父组件更新时会更新插槽生成新的component vnode,问题得到解决!
不行啊
<template> <el-main> <router-view v-slot="{ Component }"> <keep-alive :include="cacheViews"> <component :is="Component" /> </keep-alive> </router-view> </el-main> </template>
`
我这个不在App.vue中 应该跟它没关系把 store里面Name都有的啊
大佬瞅瞅? `
<router-view v-slot="{ Component }">
<transition name="fade-transform" mode="out-in">
<keep-alive :include="cachedViews">
<component :is="Component" />
</keep-alive>
</transition>
</router-view>
<script lang="ts">
import { defineComponent,computed } from 'vue'
import { useStore } from 'vuex'
export default defineComponent({
name: 'AppMain',
setup() {
const store = useStore();
// 这里绑定的值要展开为新的数组, 这里你展开了么?
const cachedViews = computed(() => [...store.getters.cachedViews])
return {
cachedViews
}
},
})
</script>
我是在这里展开的 但是没用...
暂时不知道你这个是什么情况,我试了一下即使去掉transaction组件和你一样,我这个也是正常的。按原理来说只要提示组件的更新到上一级就可以的,这是我的代码
我是在这里展开的 但是没用...
暂时不知道你这个是什么情况,我试了一下即使去掉transaction组件和你一样,我这个也是正常的。按原理来说只要提示组件的更新到上一级就可以的,这是我的代码
我确实不知道影响元素是哪个,很伤脑筋
我是在这里展开的 但是没用...
暂时不知道你这个是什么情况,我试了一下即使去掉transaction组件和你一样,我这个也是正常的。按原理来说只要提示组件的更新到上一级就可以的,这是我的代码
我确实不知道影响元素是哪个,很伤脑筋
你发个demo出来让edison大佬给你看看。
@qq10137383 搞了个线上demo居然没问题................................................................................................................................................ https://codesandbox.io/s/withered-fire-h2c35?file=/src/App.vue
How can you call yourself ak47? Are you trying to be cute or jus downright stupid?
On Jan 12, 2022, at 7:40 PM, AK47-dadada @.***> wrote:
@qq10137383 搞了个线上demo居然没问题................................................................................................................................................
— Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android. You are receiving this because you are subscribed to this thread.
How can you call yourself ak47? Are you trying to be cute or jus downright stupid? … On Jan 12, 2022, at 7:40 PM, AK47-dadada @.***> wrote: @qq10137383 搞了个线上demo居然没问题................................................................................................................................................ — Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android. You are receiving this because you are subscribed to this thread.
It's just a username. Don't make people think you're jus downright stupid
@qq10137383 兄弟 问题得到解决了 @edison1105 大佬,这个可以参照一下 http://www.jmblog.com.cn/article/61e5471af3e068311c322440
@qq10137383 兄弟 问题得到解决了 @edison1105 大佬,这个可以参照一下 http://www.jmblog.com.cn/article/61e5471af3e068311c322440
子路由的<router-view/>
,也要单独加keepalive,这跟vue2的keepalive是一致的。