You'd relate to this if you've been working with likes of Vue and React. The <template> tag also finds use in web components development. You may have considered this trivial enough to let it go without trying to find out 'why use <template> and why not <div> or even <span> which we tend to throw in wherever'. If you fit in that unsubstantial description, probably you'll get to learn something.
Before we start I'd throw in a few points to remember
1- <template> is inert
2- <template> has only one property of its own i.e. 'content'
3- <template> accepts global attrbiutes ('class', 'id', etc..) available on almost anything in HTML.
4- A template's content is not a valid target for events
When I say <template> is inert. It simply means that if you put a template tag in your HTML code, it will sit there doing nothing by itself. The template tag along with its content/children won't be rendered as a part of the DOM, not even on the next reflow. Obvious question, how is that useful? To answer whys and hows, lets first get over the whats. So, the template tag won't reveal itself in the DOM tree unless you explicitly handle it in your JavaScript and make it do so. Its important to note that the DOMParser parses everything including the temlpate tag but in this case only to check syntax validity. Alright, to get the markup inside <template></template> you need to
1- Get the content from template. The content is an instance of DocumentFragment
2- Since DocumentFragment is an implementation of the Node interface, you can use cloneNode() to get a copy of the template's content to then append it somewhere in the DOM. Alternatively, you can select a part of the content using properties available on the DocumentFragment interface or even push the entire DocumentFragment into the DOM tree. If you choose not to clone the content, you'll notice that the part of the document fragment once appended to some node in the DOM tree, is not to be found in the fragment anymore.
---------------------------- HTML ----------------------------
<ul id="container">
<b>Basket</b>
</ul>
<template id="inert">
<li>Apples</li>
<li>Oranges</li>
<li>Milk</li>
</template>
------------------------- JavaScript -------------------------
const template = document.getElementById("inert");
const documentFragment = template.content;
console.log(documentFragment.childElementCount); // 3
// const deepClone = true;
// const nodeToAppend = documentFragment.cloneNode(deepClone);
const nodeToAppend = documentFragment.firstElementChild;
const container = document.getElementById("container");
container.appendChild(nodeToAppend);
console.log(documentFragment.childElementCount); // 2
[Try on Codepen](https://codepen.io/mayankav/pen/VwbNxjQ)
That said, what does it mean when I say a template's content is not a valid target for events? We now know that content of a template is an instance of DocumentFragment which inturn can be considered a light weight version of [Document](https://developer.mozilla.org/en-US/docs/Web/API/Document). DocumentFragment doesn't make it into the real DOM tree. If you know this you won't mistake it for a target of any sort of event or you may still end up doing something like so ```javascript const template = document.getElementById("inert"); const fragment = template.content; const nodeToAppend = fragment.cloneNode(true); // just another instance of DocumentFragment nodeToAppend.addEventListener("click", () => {...}) // Mistake ```
[Easy to make mistake](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template#avoiding_documentfragment_pitfall)
That alone clarifies how <template> differs from <div>, <span> or any other tag for that matter. Template does exactly what its name suggests, its meant to be used as a temporary case for your unfinished, yet to be processed markup. You may argue that you can use the hidden property on <div> and use it like a <template> but then your unfinished markup will still be a part of the DOM causing side effects (n/w requests for images, scripts etc..) which you may not want. The template element and its contents are inert i.e. not rendered in the DOM, until you grab a reference to it with JavaScript and then append its content to some node in the DOM. You can use a <template> tag when you want to load something into the DOM after processing it in JavaScript, which is what Vue does (processes the elements and makes them reactive). Try replacing <template> with <div> in one of your SFCs and see how Vue reacts with [Vue warn]: Failed to mount component: template or render function not defined.
You could have done well without reading this but I feel it never hurts to know a little more of everything you come across at work. This shall defnitely add value in some way or the other. If you like paying attention to details, I would recommend an old post I wrote on key to responsive websites. You may find it useful. If you want to read more on html templates, go ahead.
Top comments (0)