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