template标签不渲染内容,因其内容被转为离线documentfragment挂载在content属性上;需通过content.clonenode(true)克隆后插入dom,否则无效。

template 标签不是“隐藏元素”,它根本不会进入 DOM;想复用,必须通过 content.cloneNode(true) 克隆后插入,否则什么都不会出现。
为什么直接写 template 里什么也不显示
浏览器解析到 <template></template> 时,会把内部所有内容转为一个离线的 DocumentFragment,挂载在 content 属性上。这个过程不创建真实节点、不执行 <script></script>、不加载 <img src>、不触发任何事件绑定——它只是“存着”,连 document.getElementById() 都查不到里面写的 ID。
-
template.innerHTML永远是空字符串,别试 -
template.children是空的NodeList,因为子节点全在content里 - 把
<template><div id="x"></div></template>放进页面后,document.getElementById('x')返回null
怎么安全取出并插入模板内容
必须走 content → cloneNode(true) → 插入目标容器 这条路径,缺一不可。
- 获取模板:
const tmpl = document.querySelector('#my-tmpl') - 克隆内容:
const frag = tmpl.content.cloneNode(true)(不能省略true,否则只浅克隆) - 插入 DOM:
container.append(frag)或container.appendChild(frag) - 错误写法:
container.appendChild(tmpl)—— 模板本身是元素,但没内容;container.appendChild(tmpl.content)—— 只能插入一次,第二次就失效
含表单或交互元素时容易漏掉的初始化步骤
克隆出来的 <input>、<select></select>、<textarea></textarea> 保留的是 HTML 中定义的初始 value 或 checked,不是用户当前输入值;事件监听器也不会自动带上。
- 手动设值:
frag.querySelector('input').value = user.inputValue - 手动绑定事件:
frag.querySelector('.btn').addEventListener('click', handler),或改用事件委托 - 注意
cloneNode(true)不复制运行时状态,比如已选中的 radio、滚动位置、focus 状态等
兼容性和结构陷阱
template 在 IE 中完全不可用,Edge 13+、Chrome 26+、Firefox 22+、Safari 7.1+ 支持良好,但有几个硬伤常被忽略:
- 不能作为
<table> 的直接子元素:<code><table><template>...</template></table>会被浏览器自动提到<table> 外,结构错乱 <li>不能放在 <code><script></script>、<style></style>、<iframe></iframe>内部,否则解析失败 - 服务端渲染(SSR)时,
template标签会被原样输出,客户端 JS 必须确保在 DOM 加载完成后才访问content
真正容易被忽略的一点:你每次都要重新 cloneNode(true),不能缓存 tmpl.content 直接反复插入——它是个单次使用的 DocumentFragment,插完就空了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











