SoFunction
Updated on 2025-04-05

Analysis of the principle of implementation of Vue3 KeepAlive

Ideas

First we knowKeepAliveIt is a built-in component, so it should not be too difficult for everyone to encapsulate a component. Its core logic lies in its render function. It uses map to record the components to be cached, that is,[key,vnode]form. Its core idea isLRU, When we limit maxSize, we will delete the longest-lasting unused[key, vnode], you can take a lookcache; Basically you have sorted out the idea of ​​the LRU algorithm,keepaliveYou know the principle of it almost all.

Code parsing

I've only posted the core code that can help everyone understand. The source code is located incore/package/runtime-core/src/components/

setup

const cache: Cache = new Map()
const keys: Keys = new Set()
// cache sub tree after render
let pendingCacheKey: CacheKey | null = null
const cacheSubtree = () => {
  // fix #1621, the pendingCacheKey could be 0
  if (pendingCacheKey != null) {
    (pendingCacheKey, getInnerChild())
  }
}
// When components are mounted and updated, the latest components will be cachedonMounted(cacheSubtree)
onUpdated(cacheSubtree)

render

tips: This logic is the return value of setup

  const comp =  as ConcreteComponent
  const key =  == null ? comp : 
  pendingCacheKey = key
  const cachedVNode = (key)
  
  // tips: keys are just used to collect components. The key components are actually collected in cache  if (cachedVNode) { // The node is in cache    // copy over mounted state     = 
     = 

    // Put nodes at the end of the queue    (key) 
    (key)
  } else { // Does not exist    (key) // Join the cache queue    // prune oldest entry
    // If the maximum value is exceeded, the component that has not been used for the longest time is deleted, that is, the head of the team component    if (max &&  > parseInt(max as string, 10)) { 
      pruneCacheEntry(().next().value)
    }
  }

onActivated and onDeactiveed calls

Tips: These two pieces of logic are in diff, it doesn't matter if you don't understand it. Just pay attention to a point, and the cached component node has an identifier.ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE, when mounting and uninstalling the component, we can determine whether there is this flag. If so, call onActivated or onDeactiveed; the source code is located in:core/package/runtime-core/src/renderer

if (shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {
  ;(parentComponent!.ctx as KeepAliveContext).deactivate(vnode)
  return
}

if (
   & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE ||
  (parent &&
    isAsyncWrapper() &&
     & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE)
) {
   && queuePostRenderEffect(, parentSuspense)
  if (
    __COMPAT__ &&
    isCompatEnabled(DeprecationTypes.INSTANCE_EVENT_HOOKS, instance)
  ) {
    queuePostRenderEffect(
      () => ('hook:activated'),
      parentSuspense
    )
  }
}

This is the end of this article about the implementation principle of Vue3 KeepAlive. For more information about the principle of Vue3 KeepAlive, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!