각각의 Vue 컴포넌트 인스턴스는 생성되고 소멸될 때 사전에 정의된 몇 단계의 과정을 거치게 되는데 이를 라이프사이클(lifecycle)이라 한다.
라이프사이클 훅(Lifecycle hooks)은 위의 이미지와 같은 라이프사이클 단계에서 사용자가 자신의 코드를 추가할 수 있는 단계별 기능(function)이다.
즉, 라이프 사이클의 각 단계 사이사이에 실행되는 함수들을 뜻한다.
아래와 같이 접두사 on
을 붙여 컴포넌트의 라이프사이클 훅에서 코드를 실행할 수 있다.
Creation(생성) → Mounting(장착) → Updating(수정) → Destruction(소멸)
- vue3부터는 setup()함수로 대체 -
컴포넌트 초기화 단계이며 Creation Hooks
은 라이프사이클 단계에서 가장 먼저 실행된다.
컴포넌트 인스턴스가 초기화 될 때 실행된다. data()
또는 computed
와 같은 다른 옵션을 처리하기 전에 즉시 호출된다.
컴포넌트 인스턴스가 초기화를 완료한 후 호출되는 훅.
Composition API의 setup()
훅은 Options API 훅 보다 먼저 호출된다.
beforeCreate
와 created
라이프사이클 훅은 Options API에서 사용하는 라이프사이클 훅으로 Vue3 Composition API를 활용하여 개발을 진행할 때는 setup()
함수로 대체할 수 있다.
단계를 더 잘이해하기 위해 콘솔을 찍어보자.
export default {
setup() {
console.log('setup'); //setup 출력
return {};
},
data: () => ({
dataMessage: 'data message',
})
beforeCreate() {
console.log('beforeCreate', this.dataMessage); // undefined 출력
},
created() {
console.log('create', this.dataMessage); //datamessge 출력
console.log(this); // 인스턴스 접근 가능
},
}
beforecreate는 인스턴스가 초기화를 완료하기 전에 실행되므로, this.dataMessage, this에 접근할 수 없다.
DOM에 컴포넌트를 삽입하는 단계이다. onBeforeMount
와 onMounted
가 있다.
컴포넌트가 마운트되기 직전에 호출된다.
컴포넌트가 마운트된 후에 호출된다. DOM에 접근할 수 있다.
컴포넌트의 마운트, 돔에 접근할 수 있다는게 무슨 뜻을 의미할까?
예시를 살펴보자.
<template>
<div class= "container">
<input ref="inputRef" type="text" value="hello world!">
</div>
</template>
<script>
import { onBeforeMount, onMounted, ref } from 'vue';
export default {
setup() {
console.log('setup');
const inputRef = ref(null);
onBeforeMount(() => {
console.log('onBeforeMount', inputRef.value); //null 출력
});
onMounted(() => {
console.log('onMounted', inputRef.value); //hello world! 출력
});
return { inputRef };
}
}
</script>
onBeforeMount에서는 마운트가 완료되기전이기 때문에 돔에 접근할 수 없어 null이 출력된다.
하지만, onMounted에서는 마운트가 완료된 후라 돔의 inputRef.value에 접근할 수 있다.
추가적으로, create는 부모->자식순으로 완료되고, mount는 자식->부모순으로 완료된다.
즉, 부모에서 onMounted가 호출되면 모든 자식 컴포넌트가 마운트 되었을을 의미한다.
반응형 상태 변경으로 컴포넌트의 DOM 트리가 업데이트된 후 호출될 콜백을 등록한다.
<!--message 변경될 경우 onUpdated, onBeforeUpdate호출됨-->
<template>
{{message}}
</template>
<script setup>
const message = ref('');
</script>
<!--message 변경될 경우 onUpdated, onBeforeUpdate호출되지 않음. 돔에 렌더링되어 상태변화되지 않았기때문.
-->
<template>
<!--{{message}}-->
</template>
<script setup>
const message = ref('');
</script>
반응형 상태 변경으로 컴포넌트의 DOM 트리를 업데이트하기 직전에 호출될 콜백을 등록한다.
컴포넌트에서 사용되는 반응형 상태 값이 변해서, DOM에도 그 변화를 적용시켜야 할 때가 있다. 이 때, 변화 직전에 호출되는 것이 바로 onBeforeUpdate 훅이다.
반응 상태 변경으로 인해 컴포넌트가 DOM 트리를 업데이트한 후에 호출된다.
상위 컴포넌트의 onUpdated
훅은 하위 컴포넌트의 훅 이후에 호출된다. (Child
→ Parent
)
이 훅은 다른 상태 변경으로 인해 발생할 수 있는 컴포넌트의 DOM 업데이트 후에 호출된다. 특정 상태 변경 후에 업데이트된 DOM에 액세스해야 하는 경우 대신 nextTick()
을 사용하는 것이 추천된다.
WARNING
onUpdated
훅에서 컴포넌트 상태를 변경하지 말자. 그러면 무한 업데이트 루프가 발생할 수 있다!
// message.value = 'Hello World!'로 데이터 변경
<template>
<p id="messge">{{message}}</p>
</template>
<script setup>
const message = ref('');
onBeforeUpdate(() => {
console.log('onBeforeUpdate', message.value);
//'onBeforeUpdate Hello World!' 출력
console.log('DOM Content :' , document.querySelector('#message').textContent);
// 'Dom Content: '출력
});
onUpdated(() => {
console.log('onUpdated', message.value);
//'onUpdated Hello World!' 출력
console.log('DOM Content :' , document.querySelector('#message').textContent);
// 'Dom Content: Hello World!'출력
});
</script>
onBeforeUpdate, onUpdated 모두 message.value는 'Hello World!'로 변경된 값이 출력되었다.
다만, 돔의 document.querySelector('#message').textContent 값은 onBeforeUpdate에서는 출력되지 않았다. 돔 트리를 업데이트하기 전에 호출되기 때문이다.
이에 반해 onUpdated에서는 document.querySelector('#message').textContent의 값이 'Hello World!'로 출력되었다.
돔 트리를 업데이트 한 후 호출되기 때문이다.
해체(소멸)단계 이며 onBeforeUnmount
와 onUnmounted
가 있다.
컴포넌트가 마운트 해제되기 직전에 호출된다.
컴포넌트가 마운트 해제된 후 호출된다.
ETC
onErrorCaptured()
onRenderTracked()
onRenderTriggered()
onActivated()
onDeactivated()
onServerPrefetch()
Vue3 공식문서 - LifeCycle
Vue3 기본편 - 짐코딩
드디어 벼르고 벼르던 라이프 사이클 훅에 대해 다뤘다.
업무를 하다보면, 라이프 사이클 훅을 사용해야 하는 경우들이 종종 발생한다.
컴포넌트가 마운트 되기전에 처리해야하는 로직들도 있고, 언마운트 되기 전에 처리해야하는 경우도 있다.
생명주기를 잘 알아둬야, 필요한 순간에 적절하게 사용할 수 있다.
이제 정말 vue 포스팅이 얼마남지 않았다.
끝까지 화이팅!