Full project address: vuE3-element-plus
Experience address: http://8.135.1.141/vue3-admin-plus
Series entry:
- True fragrance law! Take you to use vuE3 + VITE2 to lift backstage (entrance)
preface
When we need to cache a page in some specific scenarios, we need to use keep-alive. This paper mainly explains the principle and use of keep-alive in the architecture
Keep-alive Experience address
Architecture Keep-alive core source code analysis
src/layout/components/AppMain.vue
<transition v-if="settings.mainNeedAnimation" mode="out-in" name="fade-transform"> <! - Cache component name by keep-alive include property, such as KeepAlive -><keep-alive :include="cachedViews">
<component :is="Component" :key="key" />
</keep-alive>
</transition>
<script>
// Use vuex cachedViews to control which pages need to be cached
//cachedViews: Array<string>
const cachedViews = computed(() = > {
return store.state.app.cachedViews
})
// cachePage: true -> Cache the page after initialization
// leaveRmCachePage: true -> Remove the cache of this page after the page has left or closed
// leaveRmCachePage and cachePage come from the router configuration, as described below
let oldRoute = null
Router. path changes trigger the get function call. To get the current route, determine whether caching is required and remove caching based on cachePage and leaveRmCachePage in the route configuration information
const key = computed({
get() {
// When the page leaves, if there is cachePage=true and leaveRmCachePage=true, the cache is removed
if(oldRoute? .name) {if(oldRoute.meta? .leaveRmCachePage && oldRoute.meta? .cachePage) { store.commit('app/M_DEL_CACHED_VIEW', oldRoute.name)
}
}
// Set the cache if the page is entered with cachePage=true
if (route.name) {
if(route.meta? .cachePage) { store.commit('app/M_ADD_CACHED_VIEW', route.name)
}
}
// Save the last routing information (i.e. the routing information of the current page)
oldRoute = JSON.parse(JSON.stringify({ name: route.name, meta: route.meta }))
return route.path
}
})
</script>
Copy the code
How to use
src/router/index.js
{
path: 'keep-alive'.component: () = > import('@/views/example/keep-alive'),
name: 'KeepAlive'.// If cachePage: true is configured, the current page will be cached. The default is false
// If leaveRmCachePage: true is configured, the page will be removed from the cache after the current page leaves. The default is false
meta: { title: 'Keep-Alive'.cachePage: true.leaveRmCachePage: false}}, {path: 'router-demo-f'.name: 'routerDemoF'.hidden: true.component: () = > import('@/views/example/keep-alive/RouterDemoF.vue'),
meta: { title: 'RouterDemo-F'.cachePage: true.activeMenu: '/writing-demo/keep-alive'}}, {path: 'router-demo-s'.name: 'routerDemoS'.hidden: true.component: () = > import('@/views/example/keep-alive/RouterDemoS.vue'),
meta: { title: 'RouterDemo-S'.cachePage: true.activeMenu: '/writing-demo/keep-alive'}}Copy the code
Set cachePage or leaveRmCachePage in the meta to determine whether you need to cache and remove caching for various combinations
cachePage: true.leaveRmCachePage: true-> Pages are cached when entering and removed when leavingcachePage: falseOr do not write -> the page is not cached, press the normal pagecachePage: true.leaveRmCachePage: false-> The page is cached when entering, but not removed when leaving. The page cache will remain in place unless manually removedCopy the code
Note: Each component that needs to be cached must have the same component name as the route name, because the keepAlive cache is based on the component name
<! - use the keep alive1.Set name (required)2.Set cachePage in route configuration: cachePage --><script setup name="KeepAlive">
</script>
// Route name
{
path: 'keep-alive'.component: () = > import('@/views/example/keep-alive'),
name: 'KeepAlive',}Copy the code
What about deep page caching
Sometimes we have this business scenario
When you jump from page A to page B to page C, you need to cache pages A,B, and C. Save the status of pages A,B, and C, such as the list search criteria of page A. However, if pages A,B, and C are displayed, you need to clear the cache of pages A,B, and C at the same time, for example:
Realize the principle of
The core code
src/views/example/keep-alive/KeepAlive.vue
const $route = useRoute()
const $store = useStore()
// cacheGroup for cache groups KeepAlive->routerDemoF->routerDemoS
let cacheGroup = ['KeepAlive'.'routerDemoF'.'routerDemoS']
const unWatch = watch(
() = > $route.name,
() = > {
// If the entered page route name is not in the cacheGroup, the page cache for that cacheGroup configuration is cleared
if(! cacheGroup.includes($route.name)) {//sleep(300) -> enter other pages after the page cache clearing, for page performance optimization
useCommon()
.sleep(300)
.then(() = > {
// Traversing the cacheGroup clears the page cache
cacheGroup.forEach((fItem) = > $store.commit('app/M_DEL_CACHED_VIEW', fItem))
})
//remove watch
unWatch()
}
},
//deep: true
//immediate When the page is displayed, listen immediately
{ immediate: true})Copy the code
How does multi-level routing work for page caching
Multi-level routing experience page cache address
Core source code analysis
src/layout/components/AppMain.vue
//oldRoute: records the current route object
let oldRoute = null
//deepOldRouter: Records level 3 routing objects
let deepOldRouter = null
const key = computed({
get() {
// Get the routing level route.matched. Length
const routerLevel = route.matched.length
// Process if the route level is level 2
if (routerLevel === 2) {
// Check whether there is a deepOldRouter. If there is a deepOldRouter, the route is changed from level 3 to level 2
if(deepOldRouter? .name) {if(deepOldRouter.meta? .leaveRmCachePage && deepOldRouter.meta? .cachePage) { store.commit('app/M_DEL_CACHED_VIEW', deepOldRouter.name)
}
} else {
// Otherwise, go to the normal two-level route processing flow
if(oldRoute? .name) {if(oldRoute.meta? .leaveRmCachePage && oldRoute.meta? .cachePage) { store.commit('app/M_DEL_CACHED_VIEW', oldRoute.name)
}
}
}
// Cache the current page if there is a cachePage field
if (route.name) {
if(route.meta? .cachePage) { store.commit('app/M_ADD_CACHED_VIEW', route.name)
}
}
deepOldRouter = null
} else if (routerLevel === 3) {
// Process if the route level is level 3
// Level 3 stores the upper level of the current routing object
const parentRoute = route.matched[1]
//deepOldRouter is not empty, and deepOldRouter is not the parent of the current route, the deepOldRouter cache needs to be cleared
// Indicates that a tertiary-level route is redirected to a tertiary-level route
if(deepOldRouter? .name&&deepOldRouter.name! ==parentRoute.name) {if(deepOldRouter.meta? .leaveRmCachePage && deepOldRouter.meta? .cachePage) { store.commit('app/M_DEL_CACHED_VIEW', deepOldRouter.name)
}
} else {
// Otherwise, go to the normal two-level route processing flow
if(oldRoute? .name) {if(oldRoute.meta? .leaveRmCachePage && oldRoute.meta? .cachePage) { store.commit('app/M_DEL_CACHED_VIEW', oldRoute.name)
}
}
}
// Cache removal logic
if (route.name) {
if(route.meta? .cachePage) { deepOldRouter=parentRoute// Select name from level 2 and name from level 3
store.commit('app/M_ADD_CACHED_VIEW', deepOldRouter.name)
store.commit('app/M_ADD_CACHED_VIEW_DEEP', route.name)
}
}
}
// Save the last routing information (i.e. the routing information of the current page)
oldRoute = JSON.parse(JSON.stringify({ name: route.name, meta: route.meta }))
return route.path
}
})
Copy the code
Currently only page caching between level 2 and level 3 routes is supported, and clear caching is supported
If a clearly cached page contains a children page cache, the children page is also cleared
How to use
router/index.js
The usage is similar to that described above
{
path: 'deep-router-keep-alive'.name: 'DeepRouterKeepAlive'.component: () = > import('@/views/example/keep-alive/DeepRouterKeepAlive.vue'),
// Note: Removing the parent container page cache removes the child pages along with it
meta: { title: 'Deep KeepAlive'.cachePage: true.leaveRmCachePage: false },
alwaysShow: true.children: [{path: 'deep-children'.name: 'DeepChildren'.component: () = > import('@/views/example/keep-alive/deep-children/DeepChildren.vue'),
meta: { title: 'DeepChildren'.cachePage: true.leaveRmCachePage: true}}, {path: 'deep-children-sd'.name: 'DeepChildrenSd'.component: () = > import('@/views/example/keep-alive/deep-children/DeepChildrenSd.vue'),
meta: { title: 'DeepChildrenSd'.cachePage: true.leaveRmCachePage: false}}}]Copy the code
Note: Cache is not associated with TAB, but with routing configuration
Why is the architecture set up this way?
1. The cache is not associated with a TAB, facilitating flexible configuration of the cache. For example, when we set showTagsView to false in settings.js, we can still use the cachePage or leaveRmCachePage of the route configuration to set the cache. Showing and hiding the TagsView has no effect on the cache.
2. It is associated with route configuration, which facilitates the use of cache. For example, we can implement a combination of whether a page is cached or not, and whether a page is cached when it leaves the page, based on the cachePage or leaveRmCachePage configured for the route.
So what if I wanted to do the same thing that I did with TAB open, page cache, and TAB closed, page cache removed?
Set on the route on which you want to implement this feature page
// If cachePage: true is configured, the current page will be cached. The default is false
// If leaveRmCachePage: true is configured, the page will be removed from the cache after the current page leaves. The default is false
meta: { title: 'Keep-Alive'.cachePage: true.leaveRmCachePage: ture }
Copy the code
CachePage: true, leaveRmCachePage: ture -> Cache on entry, cache removed on closure