HLJ 发布于
2025-05-22 15:40:33
1阅读

Vue3+TypeScript路由缓存管理方案

在 Vue3 + TypeScript 项目中管理路由缓存,可以通过以下步骤实现:

一、基础配置:启用路由缓存

<!-- App.vue -->
<template>
  <router-view v-slot="{ Component }">
    <keep-alive :include="cachedViews">
      <component :is="Component" :key="$route.fullPath" />
    </keep-alive>
  </router-view>
</template>

<script setup lang="ts">
import { ref } from 'vue'
const cachedViews = ref<string[]>([])
</script>

二、类型声明扩展

// types/vue-router.d.ts
import 'vue-router'

declare module 'vue-router' {
  interface RouteMeta {
    /** 是否需要路由缓存 */
    keepAlive?: boolean
    /** 动态缓存标签(用于相同组件不同参数的场景) */
    cacheKey?: string
  }
}

三、路由配置示例

// router.ts
import { createRouter, createWebHistory } from 'vue-router'

export default createRouter({
  history: createWebHistory(),
  routes: [
    {
      path: '/list',
      name: 'ListPage',
      component: () => import('@/views/ListPage.vue'),
      meta: {
        keepAlive: true, // 需要缓存
        cacheKey: 'list'  // 唯一缓存标识
      }
    },
    {
      path: '/detail/:id',
      name: 'DetailPage',
      component: () => import('@/views/DetailPage.vue'),
      meta: {
        keepAlive: false // 不需要缓存
      }
    }
  ]
})

四、组件定义规范

<!-- ListPage.vue -->
<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
  name: 'ListPage', // 必须显式声明 name(与路由配置中的 name 一致)
  // ...
})
</script>

五、动态缓存管理方案

方案 1:自动缓存管理(推荐)

// router.ts
router.beforeEach((to, from) => {
  const cachedViews = useCachedViewsStore() // 假设使用 Pinia 管理状态
  
  // 离开需要缓存的页面时添加缓存
  if (from.meta.keepAlive && from.name) {
    const cacheKey = from.meta.cacheKey || from.name
    cachedViews.add(cacheKey)
  }

  // 进入页面时根据 meta 配置处理缓存
  if (to.meta.keepAlive && to.name) {
    const cacheKey = to.meta.cacheKey || to.name
    if (!cachedViews.includes(cacheKey)) {
      cachedViews.add(cacheKey)
    }
  }
})

方案 2:手动缓存控制

<!-- 在需要控制缓存的组件内 -->
<script setup lang="ts">
import { useRouter } from 'vue-router'
import { useCachedViewsStore } from '@/stores/cachedViews'

const router = useRouter()
const cachedViews = useCachedViewsStore()

// 进入页面时添加缓存
onMounted(() => {
  if (router.currentRoute.value.meta.keepAlive) {
    const cacheKey = router.currentRoute.value.meta.cacheKey || router.currentRoute.value.name!.toString()
    cachedViews.add(cacheKey)
  }
})

// 离开页面时移除缓存
onBeforeUnmount(() => {
  if (router.currentRoute.value.meta.autoRemoveCache) {
    const cacheKey = router.currentRoute.value.meta.cacheKey || router.currentRoute.value.name!.toString()
    cachedViews.remove(cacheKey)
  }
})
</script>

六、高级场景处理

1. 相同组件不同参数的缓存

// 动态路由配置
{
  path: '/user/:id',
  component: UserDetail,
  meta: {
    keepAlive: true,
    cacheKey: (route) => `user_${route.params.id}` // 动态生成缓存标识
  }
}

// 路由守卫中处理
router.beforeEach((to, from) => {
  if (typeof to.meta.cacheKey === 'function') {
    to.meta.cacheKey = to.meta.cacheKey(to)
  }
})

2. 缓存数量限制

<keep-alive :max="5"> <!-- 最多缓存 5 个实例 -->
  <component :is="Component" :key="cacheKey" />
</keep-alive>

七、调试技巧

// 在组件中添加生命周期钩子
onActivated(() => {
  console.log('组件被激活,可能来自缓存')
  // 这里可以添加数据刷新逻辑
})

onDeactivated(() => {
  console.log('组件被停用,进入缓存')
})

最佳实践建议

  1. 缓存策略

    • 列表页建议缓存
    • 详情页建议不缓存
    • 表单页根据业务需求决定
  2. 内存管理

    // 定时清理过期缓存
    setInterval(() => {
      cachedViews.value = cachedViews.value.filter(key => {
        return lastAccessedTime[key] > Date.now() - 30 * 60 * 1000 // 30分钟有效期
      })
    }, 5 * 60 * 1000)
    
  3. 性能优化

    <keep-alive :max="5" :exclude="/MobilePage/">
      <!-- 排除移动端页面 -->
      <component :is="Component" />
    </keep-alive>
    
  4. TypeScript 强化

    // 组件名称类型校验
    type ValidCacheNames = 'ListPage' | 'UserPage' | 'ProductPage'
    
    interface CustomRouteMeta extends RouteMeta {
      keepAlive?: boolean
      cacheKey?: ValidCacheNames | ((route: RouteLocationNormalized) => string)
    }
    

通过以上方案,可以实现以下功能:

  • 基于路由元信息的自动缓存管理
  • 支持动态路由参数缓存
  • 完善的TypeScript类型支持
  • 内存敏感型缓存控制
  • 灵活的缓存策略配置
当前文章内容为原创转载请注明出处:http://www.good1230.com/detail/2025-05-22/712.html
最后生成于 2025-06-05 15:00:33
此内容有帮助 ?
0