标签不能直接渲染内容,因为它是浏览器原生的惰性容器,内容仅解析为documentfragment但不加入dom树、不执行脚本、不加载资源,必须通过.content.clonenode(true)克隆后手动插入才生效。

为什么 标签不能直接渲染内容
<template></template> 是浏览器原生支持的惰性容器,它的内容在解析时不会被渲染、不参与 DOM 构建、也不执行其中的脚本或加载资源。这是设计使然,不是 bug。
常见错误现象是把 <template></template> 当成普通容器(比如误用 <div> 的方式),直接往里写 <code><img src="x.jpg"> 或 <script>console.log(1)</script>,结果发现图片没加载、脚本没执行、元素也查不到 —— 因为它压根没进主 DOM 树。
- 必须通过 JavaScript 手动克隆:用
.content.cloneNode(true)提取文档片段 - 必须显式插入:用
parent.appendChild(fragment)或parent.append(...fragment.children) - 不能用
innerHTML读取内容:<template></template>的innerHTML返回空字符串,得读.content.innerHTML
在自定义组件中为何总是显示 fallback 内容
当 <slot></slot> 显示默认内容(即标签内的文本或子节点)而不是传入的插槽内容时,通常是因为:父组件没正确提供具名或默认插槽内容,或者 Shadow DOM 没正确启用。
典型场景是用 customElements.define() 注册组件后,在 constructor 或 connectedCallback 中忘了调用 this.attachShadow({mode: 'open'}) —— 没 Shadow DOM,<slot></slot> 就失去作用域隔离能力,浏览器会忽略它,直接渲染内部 fallback。
- 检查 Shadow Root 是否存在:
this.shadowRoot !== null - 具名插槽需匹配
name属性:<my-card><span slot="title">Hello</span></my-card>对应<slot name="title">Default</slot> - 默认插槽(无
name)会捕获所有未分配的子节点,但仅限于 light DOM 直接子节点,嵌套一层就失效
HTML 模板组件和普通 的关键性能差异
用 <template></template> + <slot></slot> 构建组件,和纯 <div> 嵌套相比,核心差异不在语法,而在浏览器的处理时机与内存模型。
<p><code><template></template> 内容不触发样式计算、布局、绘制,也不占用渲染管线资源;而每个 <div> 即使 <code>display: none,仍会生成渲染对象(render object),参与 CSSOM 构建和重排预备工作。
- 大量重复模板(如列表项)用
<template></template> 可显著降低初始解析开销
- 动态插入时,
document.importNode(template.content, true) 比 innerHTML += str 更安全(自动转义、无 XSS 风险)
- 但注意:频繁克隆
<template>.content</template> 会产生大量文档片段对象,若不用 DocumentFragment 统一 append,可能引发 layout thrashing
哪些 HTML 标签能合法出现在 内部
<template></template> 允许几乎任何 HTML 元素作为子节点,但有两条硬性限制:
- 不能包含
<template></template> 自身(禁止嵌套)
- 不能包含
<script></script> 的执行行为 —— 虽然标签能写进去,但里面的 JS 不会自动运行,除非手动提取并 eval 或创建新 <script></script> 插入到 active DOM
另外,像 <style></style> 这类标签可以存在,但其作用域仅限于后续克隆后的 Shadow DOM(如果有的话),不会污染全局样式表。这点常被忽略,导致复用模板时样式泄漏或缺失。
用 <template></template> + <slot></slot> 构建组件,和纯 <div> 嵌套相比,核心差异不在语法,而在浏览器的处理时机与内存模型。
<p><code><template></template> 内容不触发样式计算、布局、绘制,也不占用渲染管线资源;而每个 <div> 即使 <code>display: none,仍会生成渲染对象(render object),参与 CSSOM 构建和重排预备工作。
- 大量重复模板(如列表项)用
<template></template>可显著降低初始解析开销 - 动态插入时,
document.importNode(template.content, true)比innerHTML += str更安全(自动转义、无 XSS 风险) - 但注意:频繁克隆
<template>.content</template>会产生大量文档片段对象,若不用DocumentFragment统一 append,可能引发 layout thrashing
哪些 HTML 标签能合法出现在 内部
<template></template> 允许几乎任何 HTML 元素作为子节点,但有两条硬性限制:
- 不能包含
<template></template>自身(禁止嵌套) - 不能包含
<script></script>的执行行为 —— 虽然标签能写进去,但里面的 JS 不会自动运行,除非手动提取并eval或创建新<script></script>插入到 active DOM
另外,像 <style></style> 这类标签可以存在,但其作用域仅限于后续克隆后的 Shadow DOM(如果有的话),不会污染全局样式表。这点常被忽略,导致复用模板时样式泄漏或缺失。











