keep-alive

:include 、 :exclude和abstract
include白名单,会缓存组件,exclude不会缓存,abstract看是否是抽象组件(这个到时候不说,因为害怕被追问抽象组件会不会被缓存),max,缓存上限。
(created)有cache和keys,分别存放vnode节点和对应的key值
cache中存的组件如果超过max,根据lru策略删除key[0]组件

render()会拿到组件的名字,匹配看它在不在include或exclude中,如果在include中,就缓存,如果在exclude中,就不缓存
render会把组件对象vnode,选择通过createElement或createComponent把vnode实例化,再用patch把vnode转化成真实dom
patch中vnode.componentInstance的值就是已经缓存的组件实例,那么会执行insert(parentElm, vnode.elm, refElm)逻辑,这样就直接把上一次的DOM插入到父元素中。
(首次加载被包裹组件时,vnode.componentInstance的值是undfined)

被缓存的组件实例会为其设置keepAlive= true
vnode.componentInstance和keepAlive同时为true时,不再进入$mount过程,那mounted之前的所有钩子函数(beforeCreate、created、mounted)都不再执行。

include定义缓存白名单,keep-alive会缓存
超过上限使用LRU的策略置换缓存数据

内存管理的一种页面置换算法,对于在内存中但又不用的数据块(内存块
叫做LRU,


//src/core/components/keep-alive.js

export default{
  name:'keep-alive',
  abstract: true,  //判断当前组件虚拟dom是否渲染成真实dom的关键
  props:{
    include:patternTypes,缓存白名单,
    exclude:patternTypes,缓存黑名单,
    max:[String, Number]缓存的组件
  },
  created(){
    this.cache=Object.create(null) //缓存虚拟dom
    this.key=[]   //缓存的虚拟dom
  }
  destroyed(){
  for(const key in this.cache){
    //删除所有的缓存
    pruneCacheEntry(this.cache,key,this.keys)
  }
  },
  mounted(){
    //
  }
}

created
初始化两个对象分别缓存VNode(虚拟dom和VNode对应的键的集合
destroyed
删除

actived(){}
一开始进来:
Comp A mounted
Comp A actived
点击A,切换成B:
Comp A deactivated
Comp B mounted
Comp B activated
点击又换成A:
Comp B deactivated
Comp A activated(没有执行mounted钩子)

keep-alive组件什么时候注册:
vue初始化时,会执行initGlobalAPI方法

initGlobalAPI中
会有extend(Vue.options.components, builtInComponents)

初始化vue的时候,已经把keepalive注册到全局了

keep-alive不会渲染任何实际节点  它是个抽象组件

vue初始化阶段  会执行initLifecycle方法,initLifecycle方法
会建立父组件链
当前object是abstract的话,是不会把它添加到父组件链中的,
会持续向上找,父子组件的关系中不会包含抽象组件

keep-alive。js中:
cache缓存vnode,keys保存vode对应的key值

render()返回个vnode
1.首先拿到默认插槽
const slot
然后通过 function initRender=>resolveSlots解析this.$slots

2.const vnode
getFirstComponentChild拿到第一个组件节点

3.const componentOptions
=》getComponentName  获取到组件名称

opts.Ctor.options   构造器对应的就是组件定义  .name拿到name

(include && (!name || !matcher(include, name)))
include不匹配到name  就不缓存  返回vnode(组件名在exclude中,
也是返回vnode)

const {cache:keys} 后面都是缓存vnode用的

=》matches(pattern: 可以是一个数组)=》  include/exclude可以是数组形式

//
在缓存中:
const {cache, keys}……

首先看看组件有没有key,如果没有就拼接出一个key(cid)
if(cache[key])  如果命中缓存,做一个缓存的处理(pruneCacheEntry)

如果keys.length > this.max,要做一个 缓存清理
(keep-alive本质把vnode缓存到cache中

if(cached && (current || cached.tag !== current.tag))
当前渲染的节点 如果是我们要删除的这个cache  就不执行
cached.componentInstance.$destroy()
cache[key]=null  从缓存中清掉一个

if(cache[key]){
  remove(keys, key)  首先把key删了
  keys.push(key)
}

0:14:24  什么渲染的是要删除的  不会执行$destory(),但会把它从
cache中移除??

return vnode||(slot&&slot[0])  没有vnode会返回slot第一个

接着看mounted()

pruneCache():
for( in )遍历 cache,拿到每一个节点,拿到每一个节点的名字

!filter(name)  如果名字不匹配,把它从节点中删除

0:15:41  filter  matche

keep-alive 怎么渲染到dom上 以及它的生命周期??

fucntion createComponent()
首次渲染,会执行inithook

function createComponent(){根据vnode.componentInstance
&&vnode.keepAlive

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
在首次加载被包裹组建时,vnode.componentInstance的值是undfined,再次访问被包裹组件时,vnode.componentInstance的值就是已经缓存的组件实例,那么会执行insert(parentElm, vnode.elm, refElm)逻辑,这样就直接把上一次的DOM插入到父元素中。
被缓存的组件实例会为其设置keepAlive= true
vnode.componentInstance和keepAlive同时为true时,不再进入$mount过程,那mounted之前的所有钩子函数(beforeCreate、created、mounted)都不再执行。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值