Vue 인스턴스는 생명주기(이하 라이프 사이클)가 있습니다. 이 라이프 사이클에 따라 인스턴스가 실행되거나 업데이트되거나 제거될 때 특정한 이벤트들이 발생합니다. 라이프 사이클 훅으로 인스턴스의 특정 시점에 원하는 로직을 구현할 수 있습니다.
출처: https://vuejs.org/guide/essentials/lifecycle.html#lifecycle-diagram (vue@3)
라이프사이클은 크게 4단계로 나누면
인스턴스의 생성 (create)
생성된 인스턴스를 화면에 부착 (mount)
화면에 부착된 인스턴스의 내용 갱신 (update)
인스턴스가 소멸 (unmount)
로 분류할 수 있습니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Vue Instance Lifecycle</title>
</head>
<style>
body {
font-family: 'Malgun Gothic', '맑은 고딕', serif;
}
#app {
text-align: center;
margin: 60px;
max-width: 400px;
margin: 0 auto;
display: table;
}
.num {
color: #af007e;
}
button {
font-family: 'Bitter';
background: #c62735;
color: white;
border: 0;
padding: 5px 15px;
margin: 0 10px;
border-radius: 4px;
outline: 0;
cursor: pointer;
}
h4 {
margin: 0 0 15px;
}
hr {
border-color: #f2faff;
opacity: 0.5;
margin: 15px 0;
}
</style>
<body>
<div id="app">
<h2>Vue.js 라이프사이클 샘플 예제</h2>
<button @click="toggleShow">
<span v-if="isShowing">hide</span>
<span v-else>show</span>
</button>
<hr />
<div v-if="isShowing">
<app-child></app-child>
</div>
<div id="childarea" style="display: none">
<h4>Compoent Create!</h4>
</div>
</div>
<script src="https://unpkg.com/vue@3"></script>
<!-- vue@2 cdn -->
<!-- <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> -->
<script>
const Child = {
template: '#childarea',
beforeCreate() {
alert('beforeCreate');
//can't use Data(this.message ...), events(vm.$on, vm.$once, vm.$off, vm.$emit)
},
created() {
alert('created');
//can use Data(this.title, this.titleComputed ...), events(vm.$on, vm.$once, vm.$off, vm.$emit)
//don't use $el
console.log('show is', this.show);
},
beforeMount() {
alert('beforeMount');
console.log('this.$el', this.$el);
//this.$el doesn't exist yet, but it will soon!
},
mounted() {
alert('mounted');
console.log(this.$el.textContent); // can use $el
this.$nextTick(function () {
// 모든 화면이 렌더링된 후 실행합니다.
});
},
beforeUpdate() {
alert('beforeUpdate');
},
updated() {
alert('updated');
this.$nextTick(function () {
// 모든 화면이 렌더링된 후 실행합니다.
});
},
//vue@2
// beforeDestroy() {
// alert("beforeDestroy");
// },
// destroyed() {
// alert("destroyed");
// },
//vue@3
beforeUnmount() {
console.log('beforeUnmount');
},
unmounted() {
console.log('unmounted');
},
};
const app = Vue.createApp({
data() {
return {
isShowing: false,
};
},
methods: {
toggleShow() {
this.isShowing = !this.isShowing;
},
},
components: {
appChild: Child,
},
}).mount('#app');
</script>
</body>
</html>
이 단계는 컴포넌트가 DOM에 추가되기 전입니다. 아직 컴포넌트가 돔에 추가되기 전이기 때문에 DOM에 접근하거나 this.$el
를 사용할 수 없습니다.
이 단계 관련 훅으로는 beforeCreate
과 Created
이 있습니다.
인스턴스가 초기화 된 직후, 데이터 관찰 및 이벤트/감시자(watcher) 설정 전에 동기적으로 호출됩니다. 아직 data와 events(vm.once, vm.emit)가 세팅되지 않은 시점이므로 접근하려고 하면 에러가 납니다.
여전히 템플릿(vue에서 template문법이란 화면을 조작하는 방법을 일컫습니다)과 가상DOM은 마운트 및 렌더링되지 않은 상태입니다. 인스턴스가 생성된 후 동기적으로 호출됩니다. 이 단계에서 인스턴스는 data 관찰, computed 속성, methods, watch/이벤트 콜백 등의 설정이 준비되었음을 의미하는 옵션 처리를 완료합니다. 그러나 마운트 단계가 시작되지 않았으며, $el
속성을 사용할 수 없습니다.
컴포넌트가 처음 실행될 때 그것을 Mount라고 표현합니다.
이 단계 관련 훅으로는 beforeMount
과 mounted
가 있습니다.
마운트가 시작되기 직전에 호출됩니다. render
함수가 처음으로 호출됩니다. $el
속성을 사용할 수 있습니다.
컴포넌트 초기에 세팅되어야할 데이터를 바꾸려면 created 단계를 사용하는 것이 낫습니다.
mounted
는 모든 자식 컴포넌트가 마운트되었음을 보장하지 않습니다.
출처: Vue Parent and Child lifecycle hooks
위 그림처럼 created훅은 부모에서 자식의 순서로 실행되지만 mounted는 자식에서 부모 순으로 시작되는 것을 알 수 있습니다.
전체 화면내용이 렌더링될 때까지 기다리려면, mounted
내에서 vm.$nextTick를 사용합니다. DOM
에 접근할 수 있기때문에 여기에서는 주로 AJAX 요청을 하거나, setTimeout, setInterval같은 행동을 합니다.
컴포넌트에서 사용되는 반응형 속성들이 변경되거나 어떤 이유로 재 렌더링이 발생되면 실행됩니다.
이 단계 관련 훅으로는 beforeUpdate
과 updated
가 있습니다.
DOM이 패치되기 전에 데이터가 변경될 때 호출됩니다. 이 훅은 업데이트 전에 기존 DOM에 접근 (예: 수동으로 추가된 이벤트 리스너를 제거)하기에 좋습니다. 디버깅용으로 자주 사용하는 훅입니다.
데이터가 변경되어 가상 DOM이 다시 렌더링되고 패치된 후에 호출됩니다. DOM이 업데이트 완료된 상태이므로 만약 변경된 값들을 가진 DOM을 이용해 접근하고 싶다면 이 때가 가장 적절합니다. updated
훅에서 data를 수정하게 되면 또 update
훅이 호출 되기 때문에 무한 루프에 빠질 수 있으니 주의해야합니다. 상태 변경에 반응하기 위해, 일반적으로 computed property 속성이나 watcher를 사용하는 것이 더 좋습니다.
updated
는 모든 하위 컴포넌트가 다시 렌더링되었음을 보장하지 않습니다. 전체 화면이 재렌더링 될 때까지 기다리려면, updated
내부에서 vm.$nextTick를 사용합니다.
컴포넌트가 제거되는 것을 Unmount(Destroy)라고 표현합니다. 더는 컴포넌트를 사용하지 않을 때 발생하는 이벤트가 있습니다.
이 단계 관련 훅으로는 beforeUnmount
과 unmounted
가 있습니다.
컴포넌트 인스턴스가 마운트 해제(unmounted) 되기 직전에 호출됩니다. 이 단계에서 인스턴스는 여전히 완전하게 작동합니다. beforeUpdate
에서 주로 연결했던 이벤트 리스너를 제거하는 등의 여러 가지 정리 활동을 합니다.
컴포넌트 인스턴스가 마운트 해제(unmounted)된 후 호출됩니다. 이 훅이 호출되면, 컴포넌트 인스턴스의 모든 디렉티브가 바인딩 해제되고, 모든 이벤트 리스너가 제거되며, 모든 자식 컴포넌트 컴포넌트도 마운트 해제(unmounted)됩니다.
출처: https://kr.vuejs.org/v2/guide/instance.html#라이프사이클-다이어그램 (vue@2)
출처: https://joshua1988.github.io/vue-camp/vue/life-cycle.html#라이프-사이클-다이어그램 (vue@2)
참고자료:
라이프사이클 훅 | Vue.js
[Vue.js 시작하기] - 라이프사이클
Vue.js 2.0 라이프사이클 이해하기
p.s.
React의 생명 주기(Life Cycle) - ZeroCho Blog