happyboot系列之vue3-keepalive缓存控制,支持删除缓存

983 阅读2分钟

前言

页面缓存是一种很常见的需求,特别是对于现代admin框架,不同菜单之间切换页面会有需求保持上一次页面的内容、操作状态等。为了实现这个需求我们可以使用官方内置的keep-alive组件,然后该组件只能通过组件的name去控制缓存,但是实际场景中一个页面会通过参数控制打开多次,这种情况下路由是一样的,只是参数值不同,此时keep-alive组件会出一些小问题。

目标

  • 缓存可以通过自定义行为删除
  • 相同路由的不同参数可以独立缓存,互不影响

方案

目前可以实现的方案有多种,这里罗列一些常见的。我们这里只讨论vue3,vue2不在范畴内。

魔改源码

改源码是最直接的方法,曾经我们的项目就直接改了keepalive的源码,把key也可以当做控制参数。这个改动倒是不算大,但是官方迟迟不改肯定是有原因的,而且现在针对这个需求issue也有不少。但是存在一个问题,源码修改会导致项目不方便升级依赖。 不推荐!

重新定义组件

vue3提供了defineComponent方法,可以在运行时定义一个组件。利用这个我们可以在打开页面的时候给每个内嵌在router-view组件进行重新定义,把组件的name重新设定。 推荐!

实现(伪代码)

全局代码

// 缓存
export const cached = reactive({})
export const includes = ref([])
watch(
    () => cached,
    () => {
      requestIdleCallback(() => {
        const tmp = []
        for (let cachedKey in cached) {
          if (cached[cachedKey].isKeepalive){
            tmp.push(cachedKey)
          }
        }
        includes.value = tmp
      })
    },{
      deep:true
    })

const currentMenuRoute = framework.getCurrentMenuRoute()
router.afterEach(to => {
  if (!currentMenuRoute.value){
    return
  }
  const isKeepalive = to.meta.isKeepalive || false
  const pageId = currentMenuRoute.value?.pageId
  if (cached[pageId]){
    return
  }
  cached[pageId] = {
    pageId,
    isKeepalive,
    component:null,
  }
})

实现缓存组件

cache-alive.vue

<script>
import {h, KeepAlive, toRaw} from 'vue'
import {reDefineComponent,includes} from '@/global/router'
export default {
  props: {
    is: {
      type: Object,
      require: true
    },
    route: {
      type: Object,
      require: true
    }
  },
  setup(props) {
    return ()=>h(KeepAlive, {include:toRaw(includes.value)}, {default: () => reDefineComponent(props.is,props.route)})
  },
}
</script>

具体使用

注释部分的代码是未改造前的用法。

            <router-view v-slot="{ Component,route }">
              <cache-alive :is="Component" :route="route"></cache-alive>
<!--              <keep-alive>-->
<!--                <component :is="Component" />
<!--              </keep-alive>-->
            </router-view>

实例源码参考

实例体验

tiger.happykit.org/

感谢