原理:
keep-alive是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在父组件链中;使用keep-alive包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。
因为提前被keepalive包裹了,因此在keep-alive首次加载被包裹组件时,因为keep-alive组件作为父组件,它的 render
函数会先于被包裹组件执行;先执行,就相当于要被缓存的组件被keepAlive记录了,要缓存虚拟DOM了;
Vue在初始化生命周期的时候,为组件实例建立父子关系会根据 abstract
属性决定是否忽略某个组件。在keep-alive中,设置了 abstract: true
,那Vue就会跳过该组件实例。
再次访问被包裹组件时,就直接把上一次的DOM插入到了父元素中(将缓存的DOM(vnode)插入父元素中)
一般的组件,每一次加载都会有完整的生命周期,即生命周期里面对应的钩子函数都会被触发,为什么被keep-alive包裹的组件却不是呢?
被缓存的组件实例会为其设置 keepAlive = true,那
mounted
之前的所有钩子函数( beforeCreate
、 created
、 mounted
)都不再执行。
问题1:
既然生命周期不执行,那么就说明,接口也不会请求?
问题2:
那为什么被缓存的组件在mounted的addEventListener还会每次进来执行呢?
如在mounted中绑定了window.addEventListener()
keep-alive只是缓存了虚拟DOM,下次再渲染这个组件的时候,直接把上次缓存的虚拟DOM替换给真实的DOM,既然用的上次的,生命周期就不会重新执行了,不重新执行自然就不会触发在created或者mounted接口拿到的数据,只是缓存虚拟DOM,事件并不解绑,事件还是挂载在DOM上。自然会触发。