Vue中keep-alive的原理是什么?

keep-alive是vue的一个内部组件,组件中有三个属性:include、exclude和max(LRU算法的最大存储量),他储存的是虚拟DOM,将满足条件(include和exclude)的组件在cache对象中缓存起来,在需要重新渲染的时候将VNode从cache对象中取出并进行渲染。

源码位置:src/core/components/keep-alive.js

export default {
  name: 'keep-alive',
  abstract: true,
 
  props: {
    include: patternTypes,
    exclude: patternTypes,
    max: [String, Number]
  },
 
  created () {
    this.cache = Object.create(null) // 创建缓存列表
    this.keys = [] // 创建缓存组件的key列表
  },
 
  destroyed () {
    for (const key in this.cache) {// keep-alive销毁时,循环清空所有的缓存和key
      pruneCacheEntry(this.cache, key, this.keys)
    }
  },
 
  mounted () {// 会监控include 和 include属性 进行组件的缓存处理
    this.$watch('include', val => {
      pruneCache(this, name => matches(val, name))
    })
    this.$watch('exclude', val => {
      pruneCache(this, name => !matches(val, name))
    })
  },
 
  render () {
    const slot = this.$slots.default // 会默认拿插槽
    const vnode: VNode = getFirstComponentChild(slot) // 只缓存第一个组件
    const componentOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions
    if (componentOptions) {
      // check pattern
      const name: ?string = getComponentName(componentOptions) // 取出组件的名字
      const { include, exclude } = this
      if (  // 判断是否缓存
        // not included
        (include && (!name || !matches(include, name))) ||
        // excluded
        (exclude && name && matches(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
      // 如果组件没key 就自己通过 组件的标签和key和cid 拼接一个key
      if (cache[key]) { // 如果缓存中有key
        vnode.componentInstance = cache[key].componentInstance // 直接拿到组件实例
        // make current key freshest
        remove(keys, key) // 删除当前的key // LRU 最近最久未使用法
        keys.push(key)  // 并将key放到缓存的最后面
      } else {
        cache[key] = vnode // 缓存vnode
        keys.push(key) // 将key 存入
        // prune oldest entry
        if (this.max && keys.length > parseInt(this.max)) { // 缓存的太多超过了max就需要删除掉
 
          pruneCacheEntry(cache, keys[0], keys, this._vnode) // 要删除第0个 但是现在渲染的就是第0个
        }
      }
 
      vnode.data.keepAlive = true // 并且标准keep-alive下的组件是一个缓存组件
    }
    return vnode || (slot && slot[0]) // 返回当前的虚拟节点
  }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值