You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// src/core/components/keep-alive.jsrender(){constslot=this.$slots.defaultconstvnode: VNode=getFirstComponentChild(slot)// 找到第一个子组件对象constcomponentOptions: ?VNodeComponentOptions=vnode&&vnode.componentOptionsif(componentOptions){// 存在组件参数// check patternconstname: ?string=getComponentName(componentOptions)// 组件名const{ include, exclude }=thisif(// 条件匹配// not included(include&&(!name||!matches(include,name)))||// excluded(exclude&&name&&matches(exclude,name))){returnvnode}const{ cache, keys }=thisconstkey: ?string=vnode.key==null// 定义组件的缓存key// same constructor may get registered as different local components// so cid alone is not enough (#3269)
? componentOptions.Ctor.cid+(componentOptions.tag ? `::${componentOptions.tag}` : '')
: vnode.keyif(cache[key]){// 已经缓存过该组件vnode.componentInstance=cache[key].componentInstance// make current key freshestremove(keys,key)keys.push(key)// 调整key排序}else{cache[key]=vnode// 缓存组件对象keys.push(key)// prune oldest entryif(this.max&&keys.length>parseInt(this.max)){// 超过缓存数限制,将第一个删除(LRU缓存算法)pruneCacheEntry(cache,keys[0],keys,this._vnode)}}vnode.data.keepAlive=true// 渲染和执行被包裹组件的钩子函数需要用到}returnvnode||(slot&&slot[0])}
Activity
Genzhen commentedon Jul 8, 2020
答案
一、组件中写 name 选项有什么作用?
二、keep-alive使用
三、keep-alive实现原理
1)首先看下源码
大概的分析源码,我们发现与我们定义组件的过程一样,先是设置组件名为keep-alive,其次定义了一个abstract属性,值为true。这个属性在vue的官方教程并未提及,其实是一个虚组件,后面渲染过程会利用这个属性。props属性定义了keep-alive组件支持的全部参数。
2)接下来重点就是keep-alive在它生命周期内定义了三个钩子函数了
created
初始化两个对象分别缓存VNode(虚拟DOM)和VNode对应的键集合
destroyed
删除缓存VNode还要对应执行组件实例的destory钩子函数。
删除this.cache中缓存的VNode实例。不是简单地将this.cache置为null,而是遍历调用pruneCacheEntry函数删除。
mounted
在mounted这个钩子中对include和exclude参数进行监听,然后实时地更新(删除)this.cache对象数据。pruneCache函数的核心也是去调用pruneCacheEntry。
3)render
最后就是再次渲染执行缓存和对应钩子函数了