
HTML 中 <template></template> 标签不是占位符,它根本不参与渲染
很多人一看到 <template></template> 就以为是“页面里先写个模板,后面 JS 拿来替换”,结果发现 DOM 里根本找不到它——因为浏览器压根不解析它的内容,也不创建任何节点。<template></template> 是纯声明式容器,内容被解析但被挂起,直到你手动 cloneNode(true) 或用 content 属性取出来。
常见错误现象:document.querySelector('template').innerHTML 看起来有内容,但 document.querySelector('template').children 是空的;或者直接把 <template></template> 插入页面,结果什么也没显示。
-
<template></template>内部脚本不会执行,样式不会应用,图片不会加载(除非后续被移出 template) - 它支持所有 HTML 结构,包括无效嵌套(比如在
<p></p>里放<div>),因为不走标准解析流程 <li>兼容性很好:Chrome 26+、Firefox 22+、Safari 7.1+、Edge 13+,IE 完全不支持(别考虑)</li> <h3>用 <code>template.content取内容时必须cloneNode(true)直接操作
<template>.content</template>返回的是一个DocumentFragment,它只能被插入一次。如果你把它 append 到某个元素后,再想重复用,就得重新 clone —— 否则第二次 append 会静默失败,什么也不发生。使用场景:列表渲染、模态框动态生成、表单字段批量添加。
立即学习“前端免费学习笔记(深入)”;
- 错误写法:
el.appendChild(template.content)(第一次成功,第二次 el 里啥也没有) - 正确写法:
el.appendChild(template.content.cloneNode(true)) - 注意:
cloneNode(false)只克隆顶层 fragment,不带子节点,基本没用 - 如果 template 里有
<slot></slot>或需要绑定事件,记得 clone 后再操作,原content始终是“只读模板源”
和
<script type="text/template"></script>的本质区别老项目里常看到用
<script></script>标签存模板字符串,靠 innerHTML 解析。这其实绕过了 HTML 解析器的安全校验,容易 XSS,而且无法享受浏览器对 HTML 结构的自动修复(比如自动闭合<p></p>、修正属性引号)。<template></template>是原生 HTML 解析,结构合法、可被 DevTools 检查、支持 CSS 作用域(配合<style scoped></style>在 Vue 里常见,但原生 template 不自带 scope,需手动处理)。-
<script type="text/template"></script>:内容是纯文本,JS 需要innerHTML = str才触发解析,可能执行内联 JS 或加载外部资源 -
<template></template>:内容是已解析的 DOM 片段,只是被暂停挂起,无执行风险 - 性能上:
<template></template>初始化开销略高(要走 HTML 解析),但复用时更快(不用反复 parse 字符串)
Vue/React 里为什么很少直接写
<template></template>?因为框架的模板系统(如 Vue 的
<template></template>单文件组件、React 的 JSX)在构建时就编译成 JS 渲染函数,不再依赖运行时 DOM 解析。原生<template></template>主要用在无构建工具的轻量场景,或 Web Components 自定义元素中。容易踩的坑:在 Vue SFC 里写
<template><div>xxx</div></template>,这个<template></template>是 Vue 编译器识别的语法糖,和 HTML 原生<template></template>标签无关;混用会导致结构错乱或解析失败。- 在 Web Components 中:
shadowRoot.appendChild(template.content.cloneNode(true))是标准做法 - 在普通 HTML 页面中:适合替代
innerHTML += '...'这种易错拼接 - 不要试图用 CSS 选择器直接选中
<template></template>内部元素——它们不在主 DOM 树里,得先 clone 出来
真正难的不是怎么写
<template></template>,而是想清楚什么时候该让它“活过来”:时机错了,数据没准备好;没 clone,复用就失效;和框架模板混用,边界就模糊了。 - 错误写法:











