template标签是不渲染的占位容器,用于JavaScript动态克隆纯净HTML片段;其content属性返回DocumentFragment,须用cloneNode(true)复用,innerHTML为空字符串。

template 标签本质是“不渲染的占位容器”
它不是为了直接展示,而是为后续 JavaScript 动态克隆提供干净、无副作用的 HTML 片段。浏览器解析时会跳过 <template> 内部内容,既不执行脚本、不加载图片,也不触发布局或样式计算——这点和 <script type="text/template"> 或隐藏的 <div style="display:none"> 有根本区别。
必须用 content 属性 + cloneNode 才能真正复用
直接取 template 元素的 innerHTML 会得到空字符串;正确路径是访问其 content 属性(一个 DocumentFragment),再用 cloneNode(true) 复制:
const tmpl = document.querySelector('#item-tmpl');
const instance = tmpl.content.cloneNode(true);
document.body.appendChild(instance);
-
tmpl.content是只读的,不能直接 appendChild 到页面,必须 clone -
cloneNode(true)深拷贝所有子节点,包括事件监听器(如果有的话)不会被复制,需手动绑定 - 若模板含
<slot>,仅在作为自定义元素模板时生效,独立使用时<slot>会被忽略
常见误用:当成普通 DOM 容器直接 innerHTML 插入
以下写法无效且易引发困惑:
const tmpl = document.querySelector('#item-tmpl');
document.body.innerHTML += tmpl.innerHTML; // ❌ tmpl.innerHTML 是空字符串
错误现象:页面什么也没出现,控制台无报错,但逻辑卡死在“以为拿到了 HTML 字符串”。
立即学习“前端免费学习笔记(深入)”;
- 原因:
<template>的内容不在主文档树中,innerHTML不反序列化content - 替代方案:真要字符串操作,应提前用
template.outerHTML提取原始 HTML,再用DOMParser解析,但失去content的纯净性优势 - 性能提示:频繁 cloneNode 比 innerHTML + createElement 组合稍重,但胜在结构安全、无 XSS 风险
与现代框架模板机制的本质区别
<template> 是原生、静态、无响应式的——它不编译表达式,不追踪数据变化,也不自动更新 DOM。它只解决“一次生成、多次实例化”的基础需求。
- Vue 的
<template>是编译时指令占位符,最终不产出真实 DOM 节点 - React 的 JSX 本质是 JS 函数调用,与 HTML
<template>无任何实现关联 - 若需响应式,必须配合手动监听 + 替换子节点,例如用
textContent更新文本,或用dataset绑定状态
真正容易被忽略的是:<template> 内的 <style> 和 <script> 标签虽不执行,但依然会被解析并计入文档资源计数——上线前记得清理无用样式或脚本引用。










