[Vue] Lifecycle Hooks

chaewonΒ·2024λ…„ 7μ›” 26일
0
post-thumbnail
post-custom-banner

πŸ’» Lifecycle Hooks

λ‹€μŒμ€ μΈμŠ€ν„΄μŠ€ 수λͺ… 주기에 λŒ€ν•œ λ‹€μ΄μ–΄κ·Έλž¨μ΄λ‹€. μ§€κΈˆ 진행 쀑인 λͺ¨λ“  것을 μ™„μ „νžˆ 이해할 ν•„μš”λŠ” μ—†μ§€λ§Œ 더 많이 배우고 ꡬ좕함에 따라 μœ μš©ν•œ μ°Έκ³  μžλ£Œκ°€ λœλ‹€. μžμ„Έν•œ λ‚΄μš©μ€ Vue.js 생λͺ…μ£ΌκΈ° 훅을 μ°Έκ³ ν•˜μž


1. Lifecycle Hooks 단계

Lifecycle Hooks은 크게 4λ‹¨κ³„λ‘œ λ‚˜λˆ μ§„λ‹€.
Creation(생성) > Mounting(μž₯μ°©) > Updating(μˆ˜μ •) > Destruction(μ†Œλ©Έ)

1-1. Creation

μ»΄ν¬λ„ŒνŠΈ μ΄ˆκΈ°ν™” 단계이며 Creation Hooks은 λΌμ΄ν”Œμ‚¬μ΄ν΄ λ‹¨κ³„μ—μ„œ κ°€μž₯ λ¨Όμ € μ‹€ν–‰λœλ‹€.

  • 아직 μ»΄ν¬λ„ŒνŠΈκ°€ DOM에 μΆ”κ°€λ˜κΈ° μ „μ΄λ―€λ‘œ DOM에 μ ‘κ·Όν•  수 μ—†λ‹€.
  • μ„œλ²„λ Œλ”λ§μ—μ„œ μ§€μ›λ˜λŠ” 단계
  • ν΄λΌμ΄μ–ΈνŠΈλ‚˜ μ„œλ²„ λ Œλ” λ‹¨μ—μ„œ μ²˜λ¦¬ν•΄μ•Ό ν•  일이 있으면 μ΄λ‹¨κ³„μ—μ„œ 진행

πŸ”¨ beforeCreate

μ»΄ν¬λ„ŒνŠΈ μΈμŠ€ν„΄μŠ€κ°€ μ΄ˆκΈ°ν™” 될 λ•Œ μ‹€ν–‰λœλ‹€. data() λ˜λŠ” computed와 같은 λ‹€λ₯Έ μ˜΅μ…˜μ„ μ²˜λ¦¬ν•˜κΈ° 전에 μ¦‰μ‹œ ν˜ΈμΆœλœλ‹€.

πŸ”¨ created

μ»΄ν¬λ„ŒνŠΈ μΈμŠ€ν„΄μŠ€κ°€ μ΄ˆκΈ°ν™”λ₯Ό μ™„λ£Œν•œ ν›„ ν˜ΈμΆœλ˜λŠ” 훅이닀.

πŸ”¨ setup

Composition API의 setup() 훅은 Options API ν›… 보닀 λ¨Όμ € ν˜ΈμΆœλœλ‹€. beforeCreate와 created 라이프사이클 훅은 Options APIμ—μ„œ μ‚¬μš©ν•˜λŠ” 라이프사이클 ν›…μœΌλ‘œ Vue3 Composition APIλ₯Ό ν™œμš©ν•˜μ—¬ κ°œλ°œμ„ 진행할 λ•ŒλŠ” setup()ν•¨μˆ˜λ‘œ λŒ€μ²΄ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

<script>
  export default {
  	beforeCreate(){
  	
  	},
  	created(){
  	
  	},
  	setup(){
  		//coding....
  	}
  }
</script>  

1-2. Mounting

DOM에 μ»΄ν¬λ„ŒνŠΈλ₯Ό μ‚½μž…ν•˜λŠ” 단계이닀. onBeforeMount와 onMountedκ°€ μžˆλ‹€.

  • μ„œλ²„λ Œλ”λ§μ—μ„œ μ§€μ›λ˜μ§€ μ•ŠλŠ”λ‹€.
  • 초기 λ Œλ”λ§ 직전에 돔을 λ³€κ²½ν•˜κ³ μž ν•œλ‹€λ©΄ 이 λ‹¨κ³„μ—μ„œ ν™œμš©ν•  수 μžˆλ‹€.

πŸ”¨ onBeforeMount

μ»΄ν¬λ„ŒνŠΈκ°€ 마운트되기 직전에 ν˜ΈμΆœλœλ‹€.

  • λŒ€λΆ€λΆ„μ˜ 경우 μ‚¬μš©μ„ ꢌμž₯ν•˜μ§€ μ•ŠλŠ”λ‹€.

πŸ”¨ onMounted

μ»΄ν¬λ„ŒνŠΈκ°€ 마운트된 후에 ν˜ΈμΆœλœλ‹€. DOM에 μ ‘κ·Όν•  수 μžˆλ‹€.

  • λͺ¨λ“  μžμ‹ μ»΄ν¬λ„ŒνŠΈκ°€ λ§ˆμš΄νŠΈλ˜μ—ˆμŒμ„ μ˜λ―Έν•œλ‹€.
  • 자체 DOM νŠΈλ¦¬κ°€ μƒμ„±λ˜μ–΄ μƒμœ„ μ»΄ν¬λ„ŒνŠΈμ— μ‚½μž…λ˜μ—ˆμŒμ„ μ˜λ―Έν•œλ‹€.

<template>
	<div class="container py-4">
		<input ref="inputRef" type="text" value="μ•ˆλ…•ν•˜μ„Έμš”. " />
	</div>
</template>

<script>
import { onBeforeMount, onMounted, ref } from "vue";

export default {
	setup() {
		console.log("setup");
		const inputRef = ref(null);
		//onBeforeMountλŠ” mount되기 전이라 좜λ ₯X
		onBeforeMount(() => {
			console.log("onBeforeMount", inputRef.value);
		});
		//onMountedλŠ” mount된 이후이기 λ•Œλ¬Έμ— 좜λ ₯
		onMounted(() => {
			console.log("onMounted", inputRef.value.value);
		});

		return { inputRef };
	},
	// beforeCreate() {
	// 	console.log("beforeCreate");
	// },
	// created() {
	// 	console.log("created");
	// },
};
</script>

<style lang="scss" scoped></style>

좜λ ₯ν™”λ©΄

λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈ μ•„λž˜μ— μžμ‹ μ»΄ν¬λ„ŒνŠΈκ°€ μžˆμ„κ²½μš° μ–΄λ–»κ²Œ μ²˜λ¦¬κ°€ λ˜λŠ”μ§€ ν™•μΈν•΄λ³΄μž.

λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈμ˜ setupκ³Ό onBeforeMountκ°€ λ¨Όμ € μ²˜λ¦¬κ°€ 된 ν›„ μžμ‹ μ»΄ν¬λ„ŒνŠΈκ°€ μ²˜λ¦¬κ°€ λœλ‹€. μžμ‹ μ»΄ν¬λ„ŒνŠΈμ˜ μ²˜λ¦¬κ°€ λλ‚˜λ©΄ λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈμ˜ onMountκ°€ λ§ˆμ§€λ§‰μœΌλ‘œ μ²˜λ¦¬λœλ‹€.


1-3. Updating

μ»΄ν¬λ„ŒνŠΈμ—μ„œ μ‚¬μš©λ˜λŠ” λ°˜μ‘ν˜• 데이터가 λ³€κ²½λ˜κ±°λ‚˜ μ–΄λ– ν•œ 이유둜 μž¬λ Œλ”λ§μ΄ λ°œμƒλ  λ•Œ ν˜ΈμΆœλœλ‹€.

  • λ””λ²„κΉ…μ΄λ‚˜ ν”„λ‘œνŒŒμΌλ§ 등을 μœ„ν•΄ μ»΄ν¬λ„ŒνŠΈ 재 λ Œλ”λ§ μ‹œμ μ„ μ•Œκ³  싢을 λ•Œ μ‚¬μš©ν•˜λ©΄ λœλ‹€.

πŸ”¨ onBeforeUpdate

λ°˜μ‘ν˜• μƒνƒœ λ³€κ²½μœΌλ‘œ 인해 μ»΄ν¬λ„ŒνŠΈκ°€ DOM 트리λ₯Ό μ—…λ°μ΄νŠΈν•˜κΈ° 직전에 ν˜ΈμΆœλœλ‹€.
μ»΄ν¬λ„ŒνŠΈμ—μ„œ μ‚¬μš©λ˜λŠ” λ°˜μ‘ν˜• μƒνƒœ 값이 λ³€ν•΄μ„œ, DOM에도 κ·Έ λ³€ν™”λ₯Ό μ μš©μ‹œμΌœμ•Ό ν•  λ•Œκ°€ μžˆλ‹€. 이 λ•Œ, λ³€ν™” 직전에 ν˜ΈμΆœλ˜λŠ” 것이 λ°”λ‘œ onBeforeUpdate 훅이닀.

πŸ”¨ onUpdated

λ°˜μ‘ μƒνƒœ λ³€κ²½μœΌλ‘œ 인해 μ»΄ν¬λ„ŒνŠΈκ°€ DOM 트리λ₯Ό μ—…λ°μ΄νŠΈν•œ 후에 ν˜ΈμΆœλœλ‹€.
μƒμœ„ μ»΄ν¬λ„ŒνŠΈμ˜ onUpdated 훅은 ν•˜μœ„ μ»΄ν¬λ„ŒνŠΈμ˜ ν›… 이후에 ν˜ΈμΆœλœλ‹€. (Child > Parent) 이 훅은 λ‹€λ₯Έ μƒνƒœ λ³€κ²½μœΌλ‘œ 인해 λ°œμƒν•  수 μžˆλŠ” μ»΄ν¬λ„ŒνŠΈμ˜ DOM μ—…λ°μ΄νŠΈ 후에 ν˜ΈμΆœλœλ‹€. νŠΉμ • μƒνƒœ λ³€κ²½ 후에 μ—…λ°μ΄νŠΈλœ DOM에 μ—‘μ„ΈμŠ€ν•΄μ•Ό ν•˜λŠ” 경우 λŒ€μ‹  nextTick()을 μ‚¬μš©ν•˜μž

<template>
	<div class="container py-4">
		<p id="message">{{ message }}</p>
	</div>
</template>

<script>
import { onBeforeUpdate, onUpdated, ref } from "vue";

export default {
	setup() {
		const inputRef = ref(null);
		const message = ref("");

		onBeforeUpdate(() => {
			console.log("onBefroeUpdate", message.value);
			console.log(
				"DOM Content:",
				document.querySelector("#message").textContent,
			);
		});
		onUpdated(() => {
			console.log("onUpdated", message.value);
			console.log(
				"DOM Content:",
				document.querySelector("#message").textContent,
			);
		});

		return { inputRef, message };
	},
};
</script>

<style lang="scss" scoped></style>

좜λ ₯ν™”λ©΄

λ°˜μ‘ν˜• 데이터 messageλ₯Ό μˆ˜μ •ν•˜κ²Œλ˜λ©΄ μ½˜μ†”μ—μ„œ 값을 확인할 수 μžˆλ‹€. onBeforeUpdateλŠ” DOM 트리λ₯Ό μ—…λ°μ΄νŠΈν•˜κΈ° 이전이기 λ•Œλ¬Έμ— DOM 컨텐츠λ₯Ό 가져왔을 λ•Œ 아직 이전 데이터인 λΉˆκ°’μΈ κ±Έ 확인할 수 μžˆλ‹€. onUpdated은 DOM νŠΈλ¦¬κ°€ λ³€κ²½λœ μ΄ν›„μ˜ ν˜ΈμΆœλ˜λŠ” HOOK이기 λ•Œλ¬Έμ— DOM 컨텐츠λ₯Ό κ°€μ Έμ˜€λŠ” 것을 확인할 수 μžˆλ‹€. λ‹€μ‹œ ν•œλ²ˆ λ³€κ²½ν•΄λ³΄μž.

λ°˜μ‘ν˜• λ°μ΄ν„°λŠ” λ³€κ²½λœ κ±Έ 확인할 수 μžˆμ§€λ§Œ DOM μ»¨ν…μΈ λŠ” λ³€κ²½λ˜κΈ° μ΄μ „μ˜ 데이터λ₯Ό κ°€μ Έμ˜€λŠ” 것을 확인할 수 μžˆλ‹€. onUpdated은 λ³€κ²½λœ ν›„μ˜ 데이터λ₯Ό κ°€μ Έμ˜€λŠ” 것을 확인할 수 μžˆλ‹€.


!!WARNING!!
onUpdated ν›…μ—μ„œ μ»΄ν¬λ„ŒνŠΈ μƒνƒœλ₯Ό λ³€κ²½ν•˜μ§€ 말자. 그러면 λ¬΄ν•œ μ—…λ°μ΄νŠΈ 루프가 λ°œμƒ ν•  수 μžˆλ‹€.!


1-4. Destruction

해체(μ†Œλ©Έ)단계 이며 onBeforeUnmount와 onUnmountedκ°€ μžˆλ‹€.

πŸ”¨ onBeforeUnmount

μ»΄ν¬λ„ŒνŠΈκ°€ 마운트 ν•΄μ œλ˜κΈ° 직전에 호좜

πŸ”¨ onUnmounted

μ»΄ν¬λ„ŒνŠΈκ°€ 마운트 ν•΄μ œλœ ν›„ 호좜

λΆ€λͺ¨

<template>
	<div class="container py-4">
		<button @click="visible = !visible">Toggle Child</button>
		<LifeCycleChild v-if="visible"></LifeCycleChild>
		<p id="message">{{ message }}</p>
	</div>
</template>

<script>
import { onBeforeMount, onBeforeUpdate, onMounted, onUpdated, ref } from "vue";
import LifeCycleChild from "./LifeCycleChild.vue";

export default {
	components: {
		LifeCycleChild,
	},
	setup() {
		const inputRef = ref(null);
		const message = ref("");
		const visible = ref(false);

		return { inputRef, message, visible };
	},

};
</script>

<style lang="scss" scoped></style>

μžμ‹

<template>
	<div class="card">
		<div class="card-body">Lifecycle Child</div>
		<input id="input" type="text" />
	</div>
</template>

<script>
import { onBeforeMount, onBeforeUnmount, onMounted, onUnmounted } from "vue";
export default {
	setup() {
		onBeforeMount(() => {
			console.log("[child] onBeforeMount");
		});
		onMounted(() => {
			console.log("[child] onMount");
		});
		onBeforeUnmount(() => {
			console.log("[Child] onBeforeUnmount");
			console.log(document.querySelector("#input"));
		});
		onUnmounted(() => {
			console.log("[Child] onUnmounted");
			console.log(document.querySelector("#input"));
		});
		return {};
	},
};
</script>

<style lang="scss" scoped></style>

좜λ ₯ν™”λ©΄

Toggle Child 클릭 μ‹œ LifeCycleChild.vue μ»΄ν¬λ„ŒνŠΈκ°€ μƒμ„±λ˜λ©° 마운트 λ˜μ—ˆκΈ° λ•Œλ¬Έμ— [Child] onBeforeMount와 [Child] onMountκ°€ μ‹€ν–‰λ˜λŠ” κ±Έ λ³Ό 수 μžˆλ‹€.

Toggle child λ₯Ό λ‹€μ‹œ ν΄λ¦­ν•΄μ„œ 마운트 ν•΄μ œ, μ†Œλ©Έμ‹œν‚€λ©΄
\

[Child] onBeforeUnmountκ³Ό [Child] onUnmounted이 ν˜ΈμΆœλ˜λŠ” κ±Έ λ³Ό 수 μžˆλ‹€. [Child] onBeforeUnmount은 마운트λ₯Ό ν•΄μ œν•˜κΈ° 직전에 ν˜ΈμΆœν•˜λŠ” HOOK이기 λ•Œλ¬Έμ— 아직 DOM을 κ°€μ Έμ˜¬ 수 μžˆμ§€λ§Œ [Child] onUnmountedλŠ” 마운트λ₯Ό ν•΄μ œν•œ HOOK이기 λ•Œλ¬Έμ— DOM을 가져왔을 λ•Œ μ—†λŠ” κ±Έ 확인할 수 μžˆλ‹€.


1-5. ETC

profile
μ˜λ¬Έμ€ 'μ‚Άμ˜ μˆ˜μ€€'을 κ²°μ •ν•˜κ³ , μ§ˆλ¬Έμ€ 'μ‚Ά 자체'λ₯Ό λ°”κΎΌλ‹€.
post-custom-banner

0개의 λŒ“κΈ€