全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📅 2026-05-20 8 分钟 ✍️ juanwangdev

keep-alive原理

keep-alive是抽象组件,不渲染真实DOM,通过缓存VNode实现组件实例复用,避免重复创建销毁。

keep-alive抽象组件

JavaScript
const KeepAlive = {
  name: 'keep-alive',
  abstract: true,  // 抽象组件,不渲染真实DOM
  props: {
    include: [String, RegExp, Array],
    exclude: [String, RegExp, Array],
    max: [String, Number]
  },
  created() {
    this.cache = Object.create(null)  // 缓存池
    this.keys = []                    // 缓存key列表
  }
}

abstract: true 使keep-alive不产生真实DOM节点。

缓存机制实现

JavaScript
// render函数核心逻辑
render() {
  const vnode = getFirstComponentChild(this.$slots.default)
  const name = getComponentName(vnode.componentOptions)
  
  // 匹配检查
  if (name && !matches(name, this.include, this.exclude)) {
    return vnode  // 不缓存,直接返回
  }
  
  const key = vnode.key ?? name
  const { cache, keys } = this
  
  if (cache[key]) {
    vnode.componentInstance = cache[key].componentInstance
    remove(keys, key)
    keys.push(key)  // LRU: 移到末尾
  } else {
    cache[key] = vnode
    keys.push(key)
    // 超出max限制,删除最久未使用
    if (this.max && keys.length > this.max) {
      pruneCacheEntry(cache, keys[0], keys)
    }
  }
  
  vnode.data.keepAlive = true
  return vnode
}

使用LRU策略,超出max限制时删除最久未使用的缓存。

组件激活与停用

JavaScript
// 被keep-alive包裹的组件
{
  activated() {
    // 从缓存恢复时调用
  },
  deactivated() {
    // 被缓存时调用
  }
}

通过钩子区分首次创建和从缓存恢复。

缓存清理机制

JavaScript
function pruneCacheEntry(cache, key, keys) {
  const cached = cache[key]
  if (cached) {
    cached.componentInstance.$destroy()
  }
  cache[key] = null
  remove(keys, key)
}

清除缓存时调用组件实例的 $destroy 方法清理资源。

include/exclude匹配

JavaScript
function matches(pattern, include, exclude) {
  if (include) {
    if (typeof include === 'string') {
      return pattern.includes(include)
    }
    return checkMatch(pattern, include)
  }
  if (exclude) {
    if (typeof exclude === 'string') {
      return !pattern.includes(exclude)
    }
    return !checkMatch(pattern, exclude)
  }
  return true
}

支持字符串、正则、数组三种匹配方式。

VNode复用过程

JavaScript
// 首次渲染
<keep-alive>
  <comp-a />  // 创建组件实例,缓存VNode
</keep-alive>

// 切换后
<keep-alive>
  <comp-b />  // 创建新实例,缓存VNode,A被缓存
</keep-alive>

// 再次切回
<keep-alive>
  <comp-a />  // 从缓存恢复,复用组件实例
</keep-alive>

VNode缓存包含完整的组件实例引用,恢复时直接复用。

要点总结

  • keep-alive是抽象组件(abstract: true),不渲染真实DOM
  • 通过 cache 对象和 keys 数组实现LRU缓存策略
  • 缓存的是包含组件实例引用的VNode
  • 支持 include/exclude/max 三种配置
  • activated/deactivated 钩子区分首次创建和缓存恢复
  • 清除缓存时调用 $destroy 清理组件资源

📝 发现内容有误?点击此处直接编辑

← 上一篇 组件化与渲染函数底层实现
下一篇 → nextTick实现
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库