KeepAlive provide function to delete cache
What problem does this feature solve?
We can open multiple tabs. The components corresponding to the tabs use the keepalive cache. We need to destroy the keepalive cache when closing the tabs to release the cache. We also know KeepAlive max property but that can't delete specified cache. hope expose keys and cache property in production
What does the proposed API look like?
hope expose keys and cache property in production or provide function to delete cache by key
maybe you can do it use KeepAlive
.
If use router controll it, record route:
// record tabs
const pages = reactive([]);
// when route changed, record it
router.afterEach((to) => {
const key = getKeyFromRoute(to);
if (pages.find((tab) => tab.key === key)) {
return;
}
pages.push({
key,
component: null,
});
});
// calc key of the route
function getKeyFromRoute(route) {
const keepAlive = route.meta.keepAlive ?? "path";
return keepAlive === "path"
? route.path
: keepAlive === "fullPath"
? route.fullPath
: route.name;
}
then, render router view:
// render the router view
function setup() {
// keepalive components name
const includes = ref([]);
// when tabs changed, calc the includes
watch(
() => pages,
() => {
// delay update, because of current component's onUnmounted callback
requestIdleCallback(() => {
includes.value = theme.pages
.filter((tab) => tab.keepAlive)
.map((tab) => `Route@${tab.key}`);
});
}
);
return () => (
<RouterView>
{{
default: ({ Component, route }) => {
if (!Component) return null;
const key = getKeyFromRoute(route);
// notice, use reactive var 'pages' in slots function maybe cause this slot duplicate render.
// should use other var to avoid it
const tab = pages.find((tab) => key === tab.key);
if (!tab) return null;
// wrapper component name use key of route
if (!tab.component) {
tab.component = markRaw(
defineComponent({
name: `Route@${key}`,
render: () => Component,
})
);
}
const RouterViewRender = tab.component;
return (
<KeepAlive include={includes.value}>
<RouterViewRender />
</KeepAlive>
);
},
}}
</RouterView>
);
}
when close tab, delete tab from pages:
function close(tabIndex) {
pages.slice(tabIndex, 1)
}
maybe you can do it use
KeepAlive
.If use router controll it, record route:
// record tabs const pages = reactive([]); // when route changed, record it router.afterEach((to) => { const key = getKeyFromRoute(to); if (pages.find((tab) => tab.key === key)) { return; } pages.push({ key, component: null, }); }); // calc key of the route function getKeyFromRoute(route) { const keepAlive = route.meta.keepAlive ?? "path"; return keepAlive === "path" ? route.path : keepAlive === "fullPath" ? route.fullPath : route.name; }
then, render router view:
// render the router view function setup() { // keepalive components name const includes = ref([]); // when tabs changed, calc the includes watch( () => pages, () => { // delay update, because of current component's onUnmounted callback requestIdleCallback(() => { includes.value = theme.pages .filter((tab) => tab.keepAlive) .map((tab) => `Route@${tab.key}`); }); } ); return () => ( <RouterView> {{ default: ({ Component, route }) => { if (!Component) return null; const key = getKeyFromRoute(route); // notice, use reactive var 'pages' in slots function maybe cause this slot duplicate render. // should use other var to avoid it const tab = pages.find((tab) => key === tab.key); if (!tab) return null; // wrapper component name use key of route if (!tab.component) { tab.component = markRaw( defineComponent({ name: `Route@${key}`, render: () => Component, }) ); } const RouterViewRender = tab.component; return ( <KeepAlive include={includes.value}> <RouterViewRender /> </KeepAlive> ); }, }} </RouterView> ); }
when close tab, delete tab from pages:
function close(tabIndex) { pages.slice(tabIndex, 1) }
This seems to work by redefine component name , let me try.