对于keep-ailve的理解

186 阅读2分钟

keep-alive是什么

首先在开始前,我们要先了解一下keep-alive这个组件的基本用法。 这个组件的功能只有一个那就是缓存组件,可以让其包裹的组件不销毁,起到一个缓存的作用。

接受可选的三个参数

  • max 缓存的最大组件数量,支持数字和字符串
  • include 需要缓存的数据,支持字符串,数组,正则
  • exclude 不需要缓存的数据,支持字符串,数组,正则 具体的详细介绍可以看这里

1.App.vue 常规设置

在App.vue中,使用keep-alive,并根据路由meta的keepAlive属性来判断是否需要缓存组件;keep-alive大家都很熟悉,如果启用,页面会被缓存。
注意:这里一定要设置key,要不然缓存不生效\color{red}{注意:这里一定要设置key,要不然缓存不生效}注意:这里一定要设置key,要不然缓存不生效

  <keep-alive>
    <compoent
      :is="Component"
      v-if="$route.meta.keepAlive"
      :key="$route.name"
    />
  </keep-alive>
  <compoent
    :is="Component"
    v-if="!$route.meta.keepAlive"
    :key="$route.name"
  />
</router-view>

2.设置router

meta里面的keepAlive字段用来设置页面是否需要缓存,主要给keep-alive组件使用

   path: '/',
   name: 'A',
   component: () => import('@/views/A/index.vue'),
   meta: {
     title: '首页',
     keepAlive: false // 此组件不需要被缓存
   }
},
{
   path: '/B',
   name: 'B',
   component: () => import('@/views/B/index.vue'),
   meta: {
     title: '列表',
     keepAlive: false
   }
},
{
   path: '/C',
   name: 'C',
   component: () => import('@/views/C/index.vue'),
   meta: {
     title: '详情',
     keepAlive: false
   }
}]

到这里,思路就来了,我们可以结合组件路由钩子,在页面跳转的时候,去改变meta的keepAlive值;在B页面设置路由钩子,判断B页面是进入A还是C,如果是C,那么设置B页面meta.keepAlive=true\color{red}{meta.keepAlive=true}meta.keepAlive=true,如果是A,那么反之。

3.新建useKeep.ts

因为用的是vue3,把这个功能写成一个hooks

  // 这里把targetPages参数设置为数组,因为目标页面可能有多个,比如B -> C, B -> D
  export function useKeepPage(targetPages: string[]) {
    const router = useRouter()
    
    /**
    * @description: 更新路由meta.keepAlive值
    * @param {name} string 需要修改的路由名称
    * @param {val} boolean 修改的值
    * @return {*}
    */
    const updateRouterKeepAlive = (name: string, val: boolean) => {
      router.options.routes.map((item: any) => {
        if (item.name === name) {
          item.meta.keepAlive = val
        }
      })
    }
    
    /**
    * @description: 设置页面缓存
    * @param {toName} string 目标页面name
    * @param {formName} string 来源页面name
    * @return {*}
    */
    const setKeepPage = (toName: string, formName: string) => {
      // 判断是否进入目标页面
      if (!targetPages.includes(toName)) {
        updateRouterKeepAlive(formName, false)
      } else {
        updateRouterKeepAlive(formName, true
      }
    }
    
    // 设置路由钩子
    onBeforeRouteLeave((to, form) => {
      setKeepPage(to.name as string, from.name as string)
    })
    
    return {
      setKeepPage,
      updateRouterKeepAlive
    }
  }