keep-alive 组件 vue 2.5.0

224 阅读1分钟

prune

function pruneCache (keepAliveInstance: any, filter: Function) {
  const { cache, keys, _vnode } = keepAliveInstance
  for (const key in cache) {
    const cachedNode: ?VNode = cache[key]
    if (cachedNode) { //已经缓存的node
      const name: ?string = getComponentName(cachedNode.componentOptions)
      if (name && !filter(name)) { //  缓存的node 不需要了
        //修剪缓存实例,干掉缓存实体
        pruneCacheEntry(cache, key, keys, _vnode)
      }
    }
  }
}
include 类型: [String, RegExp, Array]
  watch: {
    include (val: string | RegExp | Array<string>) {
      pruneCache(this, name => matches(val, name))
    },
    exclude (val: string | RegExp | Array<string>) {
      pruneCache(this, name => !matches(val, name))
    }
  },


 created () {
    this.cache = Object.create(null)
    this.keys = []
  },
  
  如何干掉缓存实体
  
function pruneCacheEntry (
  cache: VNodeCache,  
  key: string,
  keys: Array<string>, 来自keep-alive 组件
  current?: VNode    来自keep-alive 组件
) {
  const cached = cache[key]
  if (cached && cached !== current) {
    cached.componentInstance.$destroy() //干掉组件
  }
  cache[key] = null  // cache 中置空  为什么不直接delete 呢
  remove(keys, key) // 从keys 中删除key 
}

render

const vnode: VNode = getFirstComponentChild(this.$slots.default)
<<< 回溯下
export function getFirstComponentChild (children: ?Array<VNode>): ?VNode {
  if (Array.isArray(children)) {
    for (let i = 0; i < children.length; i++) {
      const c = children[i]
      if (isDef(c) && (isDef(c.componentOptions) || isAsyncPlaceholder(c))) {
        return c
      }
    }
  }
}
>>>
//找第一个组件
const vnode: VNode = getFirstComponentChild(this.$slots.default)
    const componentOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions
    if (componentOptions) {
      // check pattern
      const name: ?string = getComponentName(componentOptions)
      //这个组件不需要缓存
      if (name && (
        (this.include && !matches(this.include, name)) ||
        (this.exclude && matches(this.exclude, name))
      )) {
        return vnode
      }

      const { cache, keys } = this
      const key: ?string = vnode.key == null
        // same constructor may get registered as different local components
        // so cid alone is not enough (#3269)
        ? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')
        : vnode.key
      if (cache[key]) { //缓存过了
        vnode.componentInstance = cache[key].componentInstance
        // make current key freshest
        remove(keys, key)
        keys.push(key) // 把key 放到keys 的最后面(lru : old --->latest )
      } else { //没缓存
        cache[key] = vnode
        keys.push(key)
        // prune oldest entry 
        // 触发max 限制了, 要把keys中的第一个干掉  
        if (this.max && keys.length > parseInt(this.max)) {
          pruneCacheEntry(cache, keys[0], keys, this._vnode)
        }
      }

      vnode.data.keepAlive = true
    }
    return vnode