[TIL] Vue - Teleport Components

jeongjwonΒ·2024λ…„ 1μ›” 25일
0

Vue

λͺ©λ‘ 보기
18/19

μ°Έκ³ 
https://vuejs.org/guide/essentials/template-syntax.html
https://vueschool.io/lessons/vue-3-teleport?friend=vuejs
https://www.youtube.com/watch?v=Mi2TfYu0XuM






πŸ’‘ μ§€λ‚œ Modal 을 κ΅¬ν˜„ν•  λ•Œλ„ 잠깐 Teleport 에 λŒ€ν•΄ μ„€λͺ…을 ν–ˆμ§€λ§Œ, Vue μ—μ„œ Advanced Topic 이기 λ•Œλ¬Έμ— μ˜ˆμ œμ™€ ν•¨κ»˜ 더 μ‚΄νŽ΄λ³΄κ³ μž ν•œλ‹€.

μ΄λ¦„μ—μ„œ λŠκ»΄μ§€λŠ” ν…”λ ˆν¬νŠΈλŠ” μ–΄λ””λ‘ κ°€ 이동할 수 μžˆλŠ” 것을 λ§ν•œλ‹€.

//App.vue
<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png" />
    <HelloWorld msg="Vue 3" />
    <div id="purple-box" style="bordeR: purple 2px solid; min-height: 50px"></div>
</template>

App.vue λŠ” μžμ‹ μ»΄ν¬λ„ŒνŠΈ HelloWrold.vue λ₯Ό import ν•œλ‹€.

//HelloWorld.vue
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <button @click="showMessage = !showMessage">Toggle Message</button>
    <button @click="showModal = true">Show Modal</button>
    <Teleport to="#purple-box">
      <p v-if="showMessage">Hello from HelloWorld</p>
    </Teleport>
  </div>
</template>

HelloWorld.vue μ»΄ν¬λ„ŒνŠΈλŠ” λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈμ—μ„œ idκ°€ purple-box인 div νƒœκ·Έμ— 맞게 Teleport νƒœκ·Έλ‘œ to속성은 #purple-box λ₯Ό 가리킨닀.

Teleport λ₯Ό 잘 μ‚¬μš©ν•œ 것 κ°™μ§€λ§Œ, Teleport μ»΄ν¬λ„ŒνŠΈκ°€ μ§€μ •ν•œ λŒ€μƒ ('#purple-box')λ₯Ό μ°Ύμ§€ λͺ»ν•΄μ„œ λ°œμƒν•œ 였λ₯˜μ΄λ‹€. λ˜ν•œ 이 였λ₯˜λŠ” λŒ€μƒ μ—˜λ¦¬λ¨ΌνŠΈκ°€ 마운트 되기 전에 μ»΄ν¬λ„ŒνŠΈμ— ν•΄λ‹Ή λŒ€μƒμ„ μ°Ύμ§€ λͺ»ν–ˆμ„ λ•Œ λ°œμƒν•˜λ©°, 문제의 원인은 Teleport 의 λŒ€μƒμ΄ λ˜λŠ” μ—˜λ¦¬λ¨ΌνŠΈμΈ #purple-box κ°€ ν˜„μž¬ μ»΄ν¬λ„ŒνŠΈκ°€ 마운트되기 μ „μ—λŠ” μ‘΄μž¬ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ΄λ‹€.

//public > index.html
...
	<div id="app"></div>
    <!-- built files will be auto injected -->
    <div
      id="purple-box"
      style="border: purple 2px solid; min-height: 50px"
    ></div>
...

이 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ public ν΄λ”μ˜ index.html μ—μ„œ id κ°€ app 인 div νƒœκ·Έ μ•„λž˜μ— App.vue μ»΄ν¬λ„ŒνŠΈμ—μ„œ idκ°€ purple-box인 divνƒœκ·Έλ₯Ό μ—¬κΈ°λ‘œ μ΄λ™μ‹œν‚€λŠ” 것도 ν•˜λ‚˜μ˜ 방법이닀. 이 방법은 Vue 앱이 μ‹œμž‘ν•˜κΈ° 전에 #purple-box κ°€ λ¨Όμ € μƒμ„±λ˜μ–΄ 였λ₯˜λ₯Ό λ°©μ§€ν•  수 μžˆλ‹€.

ν•˜μ§€λ§Œ, Vue의 κ°•λ ₯ν•œ νŠΉμ„±μ„ ν™œμš©ν•˜λ €λ©΄ Vue μ»΄ν¬λ„ŒνŠΈ λ‚΄μ—μ„œ μ—˜λ¦¬λ¨ΌνŠΈλ₯Ό μ‘°μž‘ν•˜λŠ” 방법을 μ‚¬μš©ν•˜λŠ” 것이 더 쒋을 수 μžˆλ‹€.(예. mounted ν›…)






//App.vue
<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png" />
    <HelloWorld msg="Vue 3" />
  </div>
  <Teleport to="#purple-box">
    <button>DO NOT CLICK</button>
  </Teleport>
</template>

App.vue μ»΄ν¬λ„ŒνŠΈλ₯Ό μˆ˜μ •ν•˜κ³ , Index.html 에 div νƒœκ·Έ μ½”λ“œλ₯Ό μΆ”κ°€ν•˜λ©΄,

App.vue μ»΄ν¬λ„ŒνŠΈμ—λŠ” idκ°€ app인 div νƒœκ·Έ μ•„λž˜μ— img 와 HelloWorld μ»΄ν¬λ„ŒνŠΈκ°€ μžμ‹ μš”μ†Œλ‘œ λ“€μ–΄κ°€κ³ , Teleport νƒœκ·ΈλŠ”μžμ‹ μš”μ†Œκ°€ μ•„λ‹ˆλΌ λ°–μœΌλ‘œ λΉ μ Έμžˆλ‹€.

μŠ€νƒ€μΌ μš”μ†Œλ₯Ό μœ„ν•΄ λ°–μœΌλ‘œ λΉΌμ„œ μœ„μΉ˜μ‹œν‚€λŠ” κ²½μš°κ°€ λ°”λ‘œ μ§€λ‚œ μ‹œκ°„μ— κ΅¬ν˜„ν•΄λ³΄μ•˜λ˜ λͺ¨λ‹¬ UI 이닀.











Teleport

μ• ν”Œλ¦¬μΌ€μ΄μ…˜ DOM 계측 ꡬ쑰에 깊게 μ€‘μ²©λœλ‹€λŠ” 것을 μ˜λ―Έν•˜κΈ° λ•Œλ¬Έμ— Teleport λ₯Ό μ΄μš©ν•œλ‹€λ©΄ λ Œλ”λ§λœ DOM ꡬ쑰만 λ³€κ²½ν•˜λ©° ꡬ성 μš”μ†Œμ˜ 논리적 계측 κ΅¬μ‘°μ—λŠ” 영ν–₯을 μ£Όμ§€μ•ŠλŠ”λ‹€. 즉, Teleport ꡬ성 μš”μ†Œκ°€ ν¬ν•¨λœ 경우 ν•΄λ‹Ή ꡬ성 μš”μ†Œλ₯Ό ν¬ν•¨ν•˜λŠ” μƒμœ„ ꡬ성 μš”μ†Œμ˜ 논리적 ν•˜μœ„ ν•­λͺ©μœΌλ‘œ μœ μ§€λœλ‹€.

to 속성

teleport νƒœκ·Έλ₯Ό μ‚¬μš©ν•  λ•ŒλŠ” to 속성을 μ‚¬μš©ν•΄μ•Ό ν•œλ‹€.
to μ†μ„±μ˜ κ°’μœΌλ‘œλŠ” index.html νŒŒμΌμ—μ„œ μž‘μ„±ν•œ div νƒœκ·Έμ˜ id κ°’μœΌλ‘œ 이동할 λŒ€μƒμ„ μ§€μ •ν•œλ‹€. DOM μš”μ†Œμ˜ μ…€λ ‰ν„° λ¬Έμžμ—΄μ΄λ‚˜ μ‹€μ œ DOM μš”μ†Œ μžμ²΄κ°€ λ“€μ–΄κ°ˆ μˆ˜λ„ μžˆλ‹€.



:disabled 속성

true 와 false 의 booleanκ°’μœΌλ‘œ ν™œμ„±ν™”μ‹œν‚€κ±°λ‚˜ λΉ„ν™œμ„±ν™”μ‹œν‚¬ 수 μžˆλŠ” 속성이닀.
Vue3 의 Teleport μ»΄ν¬λ„ŒνŠΈμ—μ„œ μ§μ ‘μ μœΌλ‘œ μ œκ³΅ν•˜μ§€λŠ” μ•Šμ§€λ§Œ, νŠΉμ • 쑰건에 따라 μ„€μ •ν•  수 μžˆλ‹€.

  1. :disabled="true"
<template>
  <button @click="show = true">Show modal</button>
  <Teleport to="body" :disabled="true">
    <Modal :show="show" @close="show = false">
      <template #header>
        <h3>custom header</h3>
      </template>
    </Modal>
  </Teleport>
</template>

True 둜 μ„€μ •ν•˜κ²Œ 되면 id κ°€ app인 div νƒœκ·Έμ˜ μžμ‹μœΌλ‘œ modal이 λ‚˜νƒ€λ‚œλ‹€.



  1. :disabled="false"
<template>
  <button @click="show = true">Show modal</button>
  <Teleport to="body" :disabled="false">
    <Modal :show="show" @close="show = false">
      <template #header>
        <h3>custom header</h3>
      </template>
    </Modal>
  </Teleport>
</template>

False 둜 μ„€μ •ν•˜κ²Œ 되면 id κ°€ app인 div νƒœκ·Έμ˜ μžμ‹μœΌλ‘œ modal이 λ‚˜νƒ€λ‚œλ‹€.



true일 경우false일 경우

id κ°€ app인 div νƒœκ·Έμ˜ μžμ‹μ΄κ±°λ‚˜ μ•„μ˜ˆ λ‹€λ₯Έ div 둜 λ‚˜νƒ€λ‚΄λŠ” λ‹€λ₯Έ 점이 있긴 ν•˜μ§€λ§Œ, Teleportλ₯Ό μ΄μš©ν•˜μ—¬ μˆœκ°„μ΄λ™μ²˜λŸΌ μƒμœ„ ꡬ성 μš”μ†Œμ˜ μ£Όμž…μ΄ μ˜ˆμƒλŒ€λ‘œ μž‘λ™ν•˜κ³ , ν•˜μœ„ ꡬ성 μš”μ†Œκ°€ μ‹€μ œ μ½˜ν…μΈ κ°€ μ΄λ™λœ μœ„μΉ˜μ— 배치되게 ν•  수 μžˆλ‹€λŠ” 점이닀.






마치며

vue κ°€ μ•„λ‹Œ react λ₯Ό μ΄μš©ν•œ jsλ‚˜ ts μ—μ„œλŠ” λͺ¨λ‹¬μ„ κ΅¬ν˜„ν•˜κΈ° μœ„ν•΄μ„œλŠ” 항상 제일 λ°”κΉ₯ div νƒœκ·Έμ—μ„œ μΆ”κ°€μ‹œμΌœ μˆ˜λ™μœΌλ‘œ κ΄€λ¦¬ν•΄μ•Όν•˜λŠ” 점이 μžˆμ—ˆμ§€λ§Œ, teleport λ₯Ό μ‚¬μš©ν•¨μ— 따라 어디에든 μ΄λ™μ‹œν‚¬ 수 있기 λ•Œλ¬Έμ— μ „μ—­μ μœΌλ‘œ 관리할 수 있고, λͺ¨λ‹¬μ˜ λ§ˆν¬μ—…μ΄ μ»΄ν¬λ„ŒνŠΈ μžμ²΄μ—μ„œ 뢄리될 수 μžˆμ–΄ λͺ¨λ‹¬ μ»΄ν¬λ„ŒνŠΈλŠ” λͺ¨λ‹¬μ˜ λ™μž‘κ³Ό λ‘œμ§μ—λ§Œ 집쀑할 수 μžˆλ‹€. λ˜ν•œ , 라이프사이클을 더 μ„Έλ°€ν•˜κ²Œ μ œμ–΄ν•  수 μžˆλŠ” 이점이 μžˆμ–΄ vue 의 μ€‘μš”ν•˜κ³  μ•„μ£Ό νŽΈλ¦¬ν•œ κΈ°λŠ₯이라고 λŠκ»΄μ§„λ‹€.



0개의 λŒ“κΈ€