발표시간에 나왔던 keep-alive
에 대해서 조금 찾아보았습니다.
keep-alive
는 컴포넌트를 상태를 보존할 때 사용합니다.
keep-alive
는 비활성 컴포넌트 인스턴스를 파괴하지 않고 캐시한다고 합니다.
vue의 create-component.js
코드의 insert
hook을 보면 아래와 같은 내용이 있습니다.
insert (vnode: MountedComponentVNode) {
const { context, componentInstance } = vnode
if (!componentInstance._isMounted) {
componentInstance._isMounted = true
callHook(componentInstance, 'mounted')
}
if (vnode.data.keepAlive) {
if (context._isMounted) {
queueActivatedComponent(componentInstance)
} else {
activateChildComponent(componentInstance, true /* direct */)
}
}
}
가상노드가 keepAlive
인 경우 mount 여부에 따라서 queueActivateChildComponent
와 activateChildComponent
을 호출합니다. queueActivateChildComponent
는 전역 큐에 컴포넌트를 저장하고 activateChildComponent
를 호출하게 하는 함수입니다(사실 좀 더 복잡합니다).
결국에 두 분기 모두 activateChildComponent
를 호출하는데, 이 함수는 activated
라이프사이클을 재귀적으로 호출하는 함수입니다.
...
const activatedChildren: Array<Component> = [];
...
export function queueActivatedComponent (vm: Component) {
vm._inactive = false
activatedChildren.push(vm)
}
queueActivatedComponent 자세히 보기
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')
}
}
반대로, 컴포넌트가 삭제될 때 호출되는 destroy
hook은 아래와 같이 구현되어 있습니다.
destroy (vnode: MountedComponentVNode) {
const { componentInstance } = vnode
if (!componentInstance._isDestroyed) {
if (!vnode.data.keepAlive) {
componentInstance.$destroy()
} else {
deactivateChildComponent(componentInstance, true /* direct */)
}
}
}
keepAlive
가 아닌 경우 컴포넌트 인스턴스를 destory하고, keepAlive
일 때는 deactivateChildComponent
를 호출합니다. deactivateChildComponent
는 deactivated
라이프사이클을 재귀적으로 호출하도록 구현되어 있습니다.
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')
}
}
keep-alive
를 사용하면 컴포넌트 인스턴스가 전역 큐에 저장되고, 활성화 될 때는 기존 컴포넌트를 사용하여 activated
라이프 사이클 hook이 호출되며, 비활성화시에는 인스턴스를 소멸시키지 않고 deactivated
라이프사이클 hook이 호출되는것을 알 수 있습니다.