template 과 slot
template과 slot을 어떻게 쓸 수 있는지 너무 헷갈려서 검색해 보았다.
막연하게 사용했었는데, 위 두 태그가 HTML 태그 기반이라는 것을 알았다.
사용 방법은 Vue에서 사용하던 것과 같다.
다만, 좀 더 구체적으로 두 태그를 알게 되었다.
HTML <template> 태그 : 콘텐츠 template 요소
<template> 엘리먼트는 페이지를 불러온 순간 즉시 그려지지는 않지만,
이후 JavaScript를 사용해 인스턴스를 생성할 수 있는 HTML 코드를 담을 방법을 제공한다.
(페이지가 load 될 때, HTML 코드 조각을 담아 놓는 안 보이는 요소이다.)
<template> 엘리먼트는 콘텐츠 조각을 나중에 사용하기 위해 담아놓는 컨테이너
페이지를 불러오는 동안 구문 분석기가 <template> 요소의 콘텐츠도 읽기는 하지만, 이는 유효성을 검증하기 위함이며 렌더링 하기 위함은 아니다. => 렌더링 되지는 않는다.
<template>에 ID 를 지정하고, JS는 템플릿 안의 콘텐츠를 가져와 웹 페이지에 추가하는 데 사용된다.
페이지가 로드될 때 즉시 렌더링되지 않는 HTML을 담고 있는 HTML 요소 매커니즘이다.
그후 런타임 중에 JS에 의해 인스턴스화된다.
예시 코드
<body>
<button onclick="showContent()">숨겨진 콘텐츠를 보여줘!</button>
<template>
<h2>Test Text</h2>
</template>
</body>
<script>
function showContent() {
const temp = document.getElementsByTagName("template")[0];
const clon = temp.content.cloneNode(true);
document.body.appendChild(clon);
}
</script>
HTML <slot> 태그 : 웹 컴포넌트 Slot 요소
웹 컴포넌트 사용자가 자신만의 마크업으로 채워 별도의 DOM 트리를 생성하고, 컴포넌트와 함께 표현할 수 있는 웹 컴포넌트 내부의 플레이스 홀더이다.
보통 shadow tree에서 사용된다.
할당된 노드가 있을 경우 그걸 보여주고, 그렇지 않을 경우엔 콘텐츠를 보여준다.
예시 코드
<body>
<template>
<h1><slot name="heading"></slot></h1>
</template>
<span slot="heading">Test Text</span>
</body>
VUE에서의 template
1. DOM의 template 옵션
컴포넌트 인스턴스의 마크업으로 사용할 문자열 템플릿
템플릿은 마운트 된 엘리먼트를 한다.
템플릿에 콘텐츠 배포 슬롯(content distribution slots)이 없는 경우, 마운트 된 엘리먼트의 기존 마크업은 무시된다.
* Vue 옵션에 렌더 함수가 있으면, 템플릿은 무시된다.
2. <template>에 v-if를 이용하여 조건부 그룹으로 사용하기
<template> 엘리먼트는 눈에 보이지 않게 내부 엘리먼트를 감싸는 역할(invisible wrapper)을 하며, 최종 렌더링 결과에 포함되지 않는다.
요소들 여러 개가 있을 때, 해당 요소들을 한 번에 전환시킬 때 사용한다.
// <template>을 사용하지 않을 경우
<div class="description" v-if="condition">
<span>내용</span>
</div>
<div class="detail" v-if="condition">
<span>내용</span>
</div>
// <template>을 사용 할 경우
<template v-if="condition">
<div class="description">
<span>내용</span>
</div>
<div class="detail">
<span>내용</span>
</div>
</template>
VUE에서의 slot
템플릿의 조각을 자식 요소에 전달하고, 자식 요소가 해당 부분을 자체적으로 렌더링하도록 할 수 있다.
=> 상위 콘텐츠의 슬롯 콘텐츠가 렌더링 되어야 하는 위치를 나타낸다.
1. default slot
<button /><slot />으로 구성된 <FancyButton> 컴포넌트에 내용을 추가하면
<FancyButton> 컴포넌트의 <slot> 영역에 내용이 추가되어 렌더링 된다.
2. 이름이 있는 slot
<template>의 v-slot 속성과 <slot>의 name 속성이 매칭되어 렌더링 된다.
// parent template
<template>
<ChildComponent>
<template v-slot=“header”>헤더</tempate>
<template v-slot=“body”>바디</tempate>
</ChildComponent>
</template>
// ChildComponent template
<template>
<div>
<slot name="header">v-slot헤더가 없으면, 지금 이 텍스트가 출력된다.</slot>
<slot name="body">v-slot바디가 없으면, 지금 이 텍스트가 출력된다.</slot>
</div>
</template>
참고
MDN
<template> 태그
https://developer.mozilla.org/ko/docs/Web/HTML/Element/template
https://html.spec.whatwg.org/multipage/scripting.html#the-template-element
<slot> 태그
https://developer.mozilla.org/ko/docs/Web/HTML/Element/slot
https://html.spec.whatwg.org/multipage/scripting.html#the-slot-element
<template> 과 <slot> 함께 사용하기
https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_templates_and_slots