Vue keep-alive 的核心原理与实现

keep-alive 是 Vue 内置的抽象组件,用于缓存不活跃的组件实例,避免重复渲染。其核心原理基于 LRU(最近最少使用)缓存策略,通过维护一个缓存对象来存储组件实例。

Vue 会在组件被销毁前将实例转移到缓存中,当再次激活时直接从缓存恢复。这一过程通过 activateddeactivated 生命周期钩子触发,这两个钩子专门为 keep-alive 设计。

keep-alive 的基本用法

在模板中包裹动态组件或路由视图即可启用缓存:

<keep-alive>
  <component :is="currentComponent"></component>
</keep-alive>

对于路由场景的缓存控制:

<keep-alive :include="['Home','User']">
  <router-view></router-view>
</keep-alive>

关键属性配置

include/exclude
通过字符串、正则或数组指定需要缓存/排除的组件:

<keep-alive include="a,b" exclude="c">
  <!-- 仅缓存名称为a或b的组件 -->
</keep-alive>

max
设置最大缓存实例数(LRU淘汰策略):

<keep-alive :max="5">
  <!-- 最多保留5个缓存实例 -->
</keep-alive>

生命周期行为分析

缓存组件会额外触发两个生命周期:

  • activated:组件从缓存恢复时触发
  • deactivated:组件被缓存时触发

常规生命周期在不同场景下的表现:

  • 首次加载:created → mounted → activated
  • 缓存后再次激活:activated
  • 离开缓存:deactivated

实现自定义 keep-alive

基础实现原理示例:

const cache = Object.create(null)

export default {
  render() {
    const vnode = this.$slots.default[0]
    const key = vnode.key
    if (cache[key]) {
      vnode.componentInstance = cache[key].componentInstance
    } else {
      cache[key] = vnode
    }
    return vnode
  }
}

性能优化实践

动态缓存策略
根据业务需求动态调整缓存:

// 根据设备内存调整缓存数量
const maxCache = navigator.deviceMemory > 4 ? 10 : 5

内存管理
手动清除特定缓存:

const cache = this.$refs.keepAlive.cache
Object.keys(cache).forEach(key => {
  if (!needCache(key)) {
    cache[key].componentInstance.$destroy()
    delete cache[key]
  }
})

常见问题解决方案

组件状态保持失败
确保组件具有唯一key:

<keep-alive>
  <router-view :key="$route.fullPath"></router-view>
</keep-alive>

滚动位置恢复
结合路由的scrollBehavior:

scrollBehavior(to, from, savedPosition) {
  if (savedPosition) {
    return savedPosition
  } else if (to.meta.keepAlive) {
    return { x: 0, y: to.meta.scrollTop || 0 }
  }
  return { x: 0, y: 0 }
}

高级应用场景

嵌套路由缓存
通过路由meta控制多级缓存:

{
  path: '/parent',
  component: Parent,
  children: [
    {
      path: 'child',
      component: Child,
      meta: { keepAlive: true }
    }
  ]
}

SSR 兼容处理
服务端渲染时禁用缓存:

<keep-alive v-if="!isSSR">
  <!-- 客户端渲染才启用缓存 -->
</keep-alive>
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐