默认不渲染、不执行脚本、不加载资源,必须通过 .content.clonenode(true) 克隆后插入 dom 才生效;其内容为只读 documentfragment,直接操作会报错或移走原内容。

<template></template> 标签不是“写完就能用”的普通容器,它默认不渲染、不执行脚本、不加载资源——这是它和 <div> 或 <code><span></span> 的根本区别。想让它起作用,必须手动克隆并插入 DOM。
为什么 <template></template> 里的内容始终不显示
浏览器解析到 <template></template> 时,会跳过其内容的渲染流程:内部的 <img src> 不发起请求,<script></script> 不执行,CSS 不应用,绑定的事件监听器也不注册。它只是把结构“存起来”,等你调用 .content.cloneNode(true) 后才真正激活。
常见错误现象:
- 直接写
<template><div id="item">hello</div></template>,然后用document.getElementById('item')查不到元素 - 在
<template></template>里写了<script>console.log('run')</script>,但控制台没输出 - 用 CSS 选中
template div设置样式,页面上完全没反应
<template></template> 必须配合 .content 和 .cloneNode() 使用
它的内容藏在 .content 属性里,且是只读的 DocumentFragment。不能直接 appendChild,必须先 clone。
实操建议:
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
- 取内容:用
document.querySelector('template').content,不是.innerHTML - 插入前必 clone:直接
parent.appendChild(template.content)会报错或移走原内容(只生效一次) - 推荐写法:
parent.appendChild(template.content.cloneNode(true)) - 如果模板含表单控件,clone 后需重置
name或id,否则提交时冲突
与 <slot></slot>、<custom-element></custom-element> 配合时的边界问题
<template></template> 是 Web Components 的基础构件,但它本身不参与 Shadow DOM 渲染逻辑。放在 <shadow-root></shadow-root> 外的 <template></template> 不会自动注入;放在内部的,也得靠 JS 手动实例化。
容易踩的坑:
- 误以为
<template><slot></slot></template>能自动分发内容——不行,<slot></slot>必须出现在 Shadow DOM 的根节点下,不能包在 template 里再塞进去 - 在自定义元素
connectedCallback中直接this.appendChild(template),结果 template 元素本身被插进去了,而不是它的内容 - 用
innerHTML动态生成 template 字符串再 set,会导致 script/style 失效(parser 不会重新解析)
最常被忽略的一点:template 内部的相对路径(如 src="img/icon.png")在 clone 后仍按原始文档 base URL 解析,不是按插入位置。如果模板用于跨域 iframe 或动态路由页,得手动修正路径。










