VUE 3 停用时强制卸载
VUE 3 Force unmount when deactivated
我有 VUE 应用程序,它在路由器中使用 keep-alive
方法。许多页面只需要加载一次,但某些特定页面需要在每次激活时重新加载。
<template>
<router-view v-slot="{ Component }">
<keep-alive max="5">
<component :is="Component" />
</keep-alive>
</router-view>
<template>
我想做的是 unmount
来自 keep-alive
缓存的页面组件 deactivated
。
/* this is the loaded component */
export default {
setup() {
const state=ref({})
/*init and load data...*/
onDeactivated(()=>{
//unmount this component ???
});
return { state };
},
components: {},
};
您认为最佳做法是什么?
有条件的keep-alive
您可以 provide
methods for child routes to add/remove themselves to keep-alive
's exclude
property 通过 keepAliveExcludes
反应集。将 ref 作为计算的 array 暴露给模板(exclude
属性需要 Array
,而不是 Set
):
// App.vue
import { provide, reactive, computed } from 'vue'
export default {
setup() {
const keepAliveExcludes = reactive(new Set())
provide('keepAliveExcludes', {
add: name => keepAliveExcludes.add(name),
remove: name => keepAliveExcludes.delete(name),
})
return {
keepAliveExcludes: computed(() => Array.from(keepAliveExcludes))
}
}
}
在应用程序模板中,将 keepAliveExcludes
绑定到 <keep-alive>.exclude
:
<template>
<router-view>
<keep-alive :exclude="keepAliveExcludes">
...
</keep-alive>
</router-view>
</template>
在子路由中,inject
keepAliveExcludes
,并在需要时使用组件名称调用其 add
/remove
(例如,通过复选框):
<template>
<h1>About</h1>
<div>
<label>Keep Alive
<input type="checkbox" v-model="keepAlive">
</label>
</div>
</template>
<script>
import { ref, inject, watchEffect } from 'vue'
export default {
name: 'About',
setup() {
const { add: addKeepAliveExclude, remove: removeKeepAliveExclude } = inject('keepAliveExcludes', {})
const keepAlive = ref(true)
watchEffect(() => {
if (keepAlive.value) {
removeKeepAliveExclude?.('About')
} else {
addKeepAliveExclude?.('About')
}
})
return { keepAlive }
},
}
</script>
始终从 keep-alive
中排除
如果您需要 始终 从 keep-alive
缓存中排除组件,您可以简单地静态设置组件名称,而无需 provide
的复杂性/inject
以上。
在应用程序模板中,在 <keep-alive>.exclude
:
中指定组件名称(必须与组件声明中的 name
属性匹配)
<template>
<router-view>
<keep-alive exclude="About">
...
</keep-alive>
</router-view>
</template>
@tony19 发布了一个很棒的答案,但由于 VUE 的一个可能错误(目前我使用 3.2.6),它有一些问题。
当一个组件在启动后被排除在keep-alive之外,然后在达到最大keep-alive组件后,VUE尝试删除不存在的排除组件。
这会导致错误并停止应用程序。有关错误的更多信息,请参见下文。
我的解决方案依赖于 tony19 令人兴奋的解决方案。
我没有在加载组件后排除它,而是在加载组件之前向路由器添加规则。
const routes = [
/* ... */
{
path: "/about",
name: "AboutPage",
meta: { excludeKeepAlive: true },
component: () => import('./../components/AboutPage.vue'),
}
/* ... */
];
然后在主APP中;
/* This is the main app */
export default {
setup() {
/* ... */
const keepAliveExcludes = reactive(new Set());
cont keepAliveExcluder= {
add: name => keepAliveExcludes.add(name),
remove: name => keepAliveExcludes.delete(name),
}
router.beforeEach((to, from, next) => {
if(to.meta?.excludeKeepAlive===true){
keepAliveExcluder.add(to.name);
}
next();
});
/* ... */
return {
keepAliveExcludes: computed(() => Array.from(keepAliveExcludes))
}
}
}
有关错误的更多信息(可能是错误)
runtime-core.esm-bundler.js:2057
出现错误
Uncaught (in promise) TypeError: Cannot read property 'type' of undefined
VUE 找不到动态排除的组件。
我有 VUE 应用程序,它在路由器中使用 keep-alive
方法。许多页面只需要加载一次,但某些特定页面需要在每次激活时重新加载。
<template>
<router-view v-slot="{ Component }">
<keep-alive max="5">
<component :is="Component" />
</keep-alive>
</router-view>
<template>
我想做的是 unmount
来自 keep-alive
缓存的页面组件 deactivated
。
/* this is the loaded component */
export default {
setup() {
const state=ref({})
/*init and load data...*/
onDeactivated(()=>{
//unmount this component ???
});
return { state };
},
components: {},
};
您认为最佳做法是什么?
有条件的keep-alive
您可以 provide
methods for child routes to add/remove themselves to keep-alive
's exclude
property 通过 keepAliveExcludes
反应集。将 ref 作为计算的 array 暴露给模板(exclude
属性需要 Array
,而不是 Set
):
// App.vue
import { provide, reactive, computed } from 'vue'
export default {
setup() {
const keepAliveExcludes = reactive(new Set())
provide('keepAliveExcludes', {
add: name => keepAliveExcludes.add(name),
remove: name => keepAliveExcludes.delete(name),
})
return {
keepAliveExcludes: computed(() => Array.from(keepAliveExcludes))
}
}
}
在应用程序模板中,将 keepAliveExcludes
绑定到 <keep-alive>.exclude
:
<template>
<router-view>
<keep-alive :exclude="keepAliveExcludes">
...
</keep-alive>
</router-view>
</template>
在子路由中,inject
keepAliveExcludes
,并在需要时使用组件名称调用其 add
/remove
(例如,通过复选框):
<template>
<h1>About</h1>
<div>
<label>Keep Alive
<input type="checkbox" v-model="keepAlive">
</label>
</div>
</template>
<script>
import { ref, inject, watchEffect } from 'vue'
export default {
name: 'About',
setup() {
const { add: addKeepAliveExclude, remove: removeKeepAliveExclude } = inject('keepAliveExcludes', {})
const keepAlive = ref(true)
watchEffect(() => {
if (keepAlive.value) {
removeKeepAliveExclude?.('About')
} else {
addKeepAliveExclude?.('About')
}
})
return { keepAlive }
},
}
</script>
始终从 keep-alive
中排除
如果您需要 始终 从 keep-alive
缓存中排除组件,您可以简单地静态设置组件名称,而无需 provide
的复杂性/inject
以上。
在应用程序模板中,在 <keep-alive>.exclude
:
name
属性匹配)
<template>
<router-view>
<keep-alive exclude="About">
...
</keep-alive>
</router-view>
</template>
@tony19 发布了一个很棒的答案,但由于 VUE 的一个可能错误(目前我使用 3.2.6),它有一些问题。
当一个组件在启动后被排除在keep-alive之外,然后在达到最大keep-alive组件后,VUE尝试删除不存在的排除组件。
这会导致错误并停止应用程序。有关错误的更多信息,请参见下文。
我的解决方案依赖于 tony19 令人兴奋的解决方案。
我没有在加载组件后排除它,而是在加载组件之前向路由器添加规则。
const routes = [
/* ... */
{
path: "/about",
name: "AboutPage",
meta: { excludeKeepAlive: true },
component: () => import('./../components/AboutPage.vue'),
}
/* ... */
];
然后在主APP中;
/* This is the main app */
export default {
setup() {
/* ... */
const keepAliveExcludes = reactive(new Set());
cont keepAliveExcluder= {
add: name => keepAliveExcludes.add(name),
remove: name => keepAliveExcludes.delete(name),
}
router.beforeEach((to, from, next) => {
if(to.meta?.excludeKeepAlive===true){
keepAliveExcluder.add(to.name);
}
next();
});
/* ... */
return {
keepAliveExcludes: computed(() => Array.from(keepAliveExcludes))
}
}
}
有关错误的更多信息(可能是错误)
runtime-core.esm-bundler.js:2057
Uncaught (in promise) TypeError: Cannot read property 'type' of undefined
VUE 找不到动态排除的组件。