IT/언어

[Vue.js] <template> 태그의 몇 가지 역할

개발자 두더지 2023. 4. 19. 21:57
728x90

일본의 한 블로그 글을 번역한 포스트입니다. 오역 및 의역, 직역이 있을 수 있으며 틀린 내용은 지적해주시면 감사하겠습니다.

 

 공식 문서에 template 태그의 다양한 역할에 대해 기재되어 있지만, 적혀 있는 곳들이 다 분산되어 있기 때문에 혼란되기 쉽다. 따라서 이번 포스트를 통해서 정리하고자한다.

 <temaplate> 태그는 다음과 같은 역할이 있다.

  • 조건이 붙은 랜더링으로 여러개의 요소를 대상으로 하는 경우(v-if)
  • 리스트 랜더링으로 여러개의  요소를 대상으로 하는 경우 (v-for)
  • 이름이 붙은 스코프 (v-slot)
  • 단일 파일의 컴포넌트  

 

 

조건이 붙은 랜더링으로 여러 개의 요소를 대상으로 하는 경우 (v-if)


 공식 문서의 예를 인용해보자면 다음과 같다.

<template v-if="ok">
  <h1>Title</h1>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</template>

 v-if 속성을 가진 <template> 태그는 조건이 붙은 랜더링이다. 이 예제로 설명하자면 ok가 true인 경우 아래와 같이 랜더링된다.

  <h1>Title</h1>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>

<template> 태그 자체는 랜더링되지 않는다.

 

 

리스트 랜더링으로 여러 개의 요소를 대상으로 하는 경우 (v-for)


 공식 문서의 예를 인용하자면 다음과 같다.

<ul>
  <template v-for="item in items">
    <li>{{ item.msg }}</li>
    <li class="divider" role="presentation"></li>
  </template>
</ul>

 v-for 속성을 가진 <template> 태그는 리스트 랜더링이다. 위 예로 설명하자면 예를 들어 items가[{msg: "foo"},{msg: "bar"},{msg: "baz"}]  가 라면, 아래와 같이 랜더링 된다.

<ul>
    <li>foo</li>
    <li class="divider" role="presentation"></li>
    <li>bar</li>
    <li class="divider" role="presentation"></li>
    <li>baz</li>
    <li class="divider" role="presentation"></li>
</ul>

 이번에도 <template> 태그 자체는 랜더링 되지 않는다.

 

 

이름이 붙은 스코프 (v-slot)


 본격적인 내용에 들어가기에 앞서 먼저 "컴포넌트"를 이해해둘 필요가 있다. 상세하게 설명하게 된다면 내용이 장황해지므로 간단하게 언급하고 넘어가도록 하겠다.

 "컴포넌트"는 Vue 요소를 부품화한 것이므로 "슬롯"은 컴포넌트를 이용할 때에 컴포넌트를 호출하는 쪽에서 데이터 등을 전달하는 것이 가능한데, 그러한 것을 끼워 넣는 요소를 말한다.  

 공식 문서에 있는 예를 조금 수정해서 인용하고자 한다. base-layout이라는 컴포넌트가 아래와 같이 구성되어 있다고 하자.

<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot name="main"></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>

 base-layout을 호출하는 쪽에서는 슬롯에 넣고 싶은 내용을 v-slot 속성을 지정한 <template> 태그로 지정한다.

<base-layout>
  <template v-slot:header>
    <h1>Here might be a page title</h1>
  </template>

  <template v-slot:main>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
  </template>

  <template v-slot:footer>
    <p>Here's some contact info</p>
  </template>
</base-layout>

 실제 랜더링되는 것은 다음과 같다.

<div class="container">
  <header>
    <h1>Here might be a page title</h1>
  </header>
  <main>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
  </main>
  <footer>
    <p>Here's some contact info</p>
  </footer>
</div>

 

 

단일 파일의 컴포넌트


 중간 규모 이상의 어플리케이션을 만들어 가는 경우, 컴포넌트를 각각의 파일(.vue 파일)으로 분할하여 webpack등으로 빌드하는 흐름이 된다.

 이때, 컴포넌트화된 .vue파일에서는 HTML부, JavaScript부, CSS부를 분리했을 때, HTML부의 루트 요소로서 <template>태그를 지정한다.

 공식 문서예를 인용하자면 다음과 같다.

<template>
  <p>{{ greeting }} World!</p>
</template>

<script>
module.exports = { 
  data: function () { 
    return { 
      greeting: 'Hello' 
    } 
  } 
} 
</script> 

<style scoped>
p {
  font-size: 2em;
  text-align: center;
}
</style>

참고자료

https://qiita.com/m_norii/items/c52171fd09c4504f8b81

728x90