被
keep-alive緩存的組件會(huì)多兩個(gè)生命周期activated、deactivated,緩存后的組件經(jīng)常會(huì)用activated這個(gè)生命周期,那么這兩個(gè)生命周期和vue的其他生命周期怎么排序執(zhí)行的呢?
我們知道VUE的其他的生命周期是這樣的:

activated 這個(gè)生命周期呢?
我們可以從源碼src/core/vdom/create-component.js看到:
insert (vnode: MountedComponentVNode) {
const { context, componentInstance } = vnode
if (!componentInstance._isMounted) {
componentInstance._isMounted = true
callHook(componentInstance, 'mounted')
}
if (vnode.data.keepAlive) {
if (context._isMounted) {
// vue-router#1212
// During updates, a kept-alive component's child components may
// change, so directly walking the tree here may call activated hooks
// on incorrect children. Instead we push them into a queue which will
// be processed after the whole patch process ended.
queueActivatedComponent(componentInstance)
} else {
activateChildComponent(componentInstance, true /* direct */)
}
}
}
從上面源碼可以看到,組件的mounted掛載后,回去判斷當(dāng)前組件是否vnode.data.keepAlive ,如果context._isMounted是true那么有可能keep-alive組件的子組件也許會(huì)改變,因此直接在此處行走樹(shù)可能會(huì)在不正確的子組件上調(diào)用已激活的鉤子。相反我們把它們推入隊(duì)列,整個(gè)patch過(guò)程結(jié)束后將對(duì)其進(jìn)行處理。
src/core/observer/scheduler.js
/**
* Queue a kept-alive component that was activated during the patch.
* The queue will be processed after the entire tree has been patched.
*/
export function queueActivatedComponent (vm: Component) {
// setting _inactive to false here so that a render function can
// rely on checking whether it's in an inactive tree (e.g. router-view)
vm._inactive = false
activatedChildren.push(vm)
}
...
...
/**
* Push a watcher into the watcher queue.
* Jobs with duplicate IDs will be skipped unless it's
* pushed when the queue is being flushed.
*/
export function queueWatcher (watcher: Watcher) {
const id = watcher.id
if (has[id] == null) {
has[id] = true
if (!flushing) {
queue.push(watcher)
} else {
// if already flushing, splice the watcher based on its id
// if already past its id, it will be run next immediately.
let i = queue.length - 1
while (i > index && queue[i].id > watcher.id) {
i--
}
queue.splice(i + 1, 0, watcher)
}
// queue the flush
if (!waiting) {
waiting = true
if (process.env.NODE_ENV !== 'production' && !config.async) {
flushSchedulerQueue()
return
}
nextTick(flushSchedulerQueue)
}
}
}
上面代碼是做隊(duì)列處理。
src/core/instance/lifecycle.js
export function activateChildComponent (vm: Component, direct?: boolean) {
if (direct) {
vm._directInactive = false
if (isInInactiveTree(vm)) {
return
}
} else if (vm._directInactive) {
return
}
if (vm._inactive || vm._inactive === null) {
vm._inactive = false
for (let i = 0; i < vm.$children.length; i++) {
activateChildComponent(vm.$children[i])
}
callHook(vm, 'activated')
}
}
上面是發(fā)起activated
deactivated那么是在什么時(shí)候調(diào)用的呢?
src/core/instance/lifecycle.js
export function deactivateChildComponent (vm: Component, direct?: boolean) {
if (direct) {
vm._directInactive = true
if (isInInactiveTree(vm)) {
return
}
}
if (!vm._inactive) {
vm._inactive = true
for (let i = 0; i < vm.$children.length; i++) {
deactivateChildComponent(vm.$children[i])
}
callHook(vm, 'deactivated')
}
}
src/core/vdom/create-component.js
destroy (vnode: MountedComponentVNode) {
const { componentInstance } = vnode
if (!componentInstance._isDestroyed) {
if (!vnode.data.keepAlive) {
componentInstance.$destroy()
} else {
deactivateChildComponent(componentInstance, true /* direct */)
}
}
}
組件是vnode.data.keepAlive的時(shí)候直接調(diào)用deactivateChildComponent,發(fā)起deactivated,不走$destroy。
以上是VUE里面keep-alive中activated、deactivated兩個(gè)點(diǎn)發(fā)生的生命周期位置,如果有誤歡迎大家在評(píng)論里面指正。