HTML template标签如何动态设置content属性值?
- 内容介绍
- 文章标签
- 相关推荐
本文共计743个文字,预计阅读时间需要3分钟。
直接使用 `appendChild(template.content)` 会清空 `template` 内的内容,并且后续调用会获取到空 `fragment`。因为 `DocumentFragment` 只能有一个父节点,移动操作是剪切而非复制。
正确做法永远是克隆:
-
template.content.cloneNode(true)—— 深克隆全部子节点(推荐) -
document.importNode(template.content, true)—— 语义更明确,尤其在跨文档场景下更安全 - 不要用
innerHTML读取<template>内容,它返回空字符串
template 内部脚本、图片、样式全不生效,别指望自动触发
<template> 的内容处于“离线状态”:里面的 <script> 不执行,<img src> 不发请求,<style> 不参与 CSSOM 构建,for 属性指向的表单控件也不建立关联。
这意味着:
立即学习“前端免费学习笔记(深入)”;
- 想运行脚本?得手动创建新
<script>元素并设置textContent或src后插入 - 想加载图片?克隆后插入 DOM 才会触发请求
- 想用内联样式?必须插入到
<head>或 shadow root 中才起作用 - 自定义元素不会在 template 内升级,只有克隆进活动 DOM 后才会触发
connectedCallback
用 querySelector 拿结构时,必须从 content 出发
template.querySelector('div') 返回 null,因为 template 元素自身不包含子节点——所有内容都封装在 content 里。
正确路径只有这一条:
-
template.content.querySelector('div')✅ -
template.content.firstElementChild✅(适合简单结构) -
template.content.children是实时 HTMLCollection,但长度可能为 0(如果含文本节点或注释) - 别对
template本身调用getElementsByTagName,它查不到内部元素
Web Components 中 template 是 shadow DOM 的标准搭档
在自定义元素中,<template> 几乎总是配合 attachShadow 使用,而不是插入到 light DOM。
原因很实际:
- 避免模板内样式污染全局(
<style>插入 light DOM 会全局生效) - 保证事件委托和选择器作用域可控
- shadow root 能真正隔离 template 克隆后的实例
- 现代框架(如 Lit)底层就是靠
template.content.cloneNode(true)+root.appendChild()实现渲染
容易忽略的一点:如果你把 template 内容克隆进 light DOM,又用了 class 名(比如 .card),那它就和页面其他同名 class 完全混在一起——没有封装,也没有复用优势。
本文共计743个文字,预计阅读时间需要3分钟。
直接使用 `appendChild(template.content)` 会清空 `template` 内的内容,并且后续调用会获取到空 `fragment`。因为 `DocumentFragment` 只能有一个父节点,移动操作是剪切而非复制。
正确做法永远是克隆:
-
template.content.cloneNode(true)—— 深克隆全部子节点(推荐) -
document.importNode(template.content, true)—— 语义更明确,尤其在跨文档场景下更安全 - 不要用
innerHTML读取<template>内容,它返回空字符串
template 内部脚本、图片、样式全不生效,别指望自动触发
<template> 的内容处于“离线状态”:里面的 <script> 不执行,<img src> 不发请求,<style> 不参与 CSSOM 构建,for 属性指向的表单控件也不建立关联。
这意味着:
立即学习“前端免费学习笔记(深入)”;
- 想运行脚本?得手动创建新
<script>元素并设置textContent或src后插入 - 想加载图片?克隆后插入 DOM 才会触发请求
- 想用内联样式?必须插入到
<head>或 shadow root 中才起作用 - 自定义元素不会在 template 内升级,只有克隆进活动 DOM 后才会触发
connectedCallback
用 querySelector 拿结构时,必须从 content 出发
template.querySelector('div') 返回 null,因为 template 元素自身不包含子节点——所有内容都封装在 content 里。
正确路径只有这一条:
-
template.content.querySelector('div')✅ -
template.content.firstElementChild✅(适合简单结构) -
template.content.children是实时 HTMLCollection,但长度可能为 0(如果含文本节点或注释) - 别对
template本身调用getElementsByTagName,它查不到内部元素
Web Components 中 template 是 shadow DOM 的标准搭档
在自定义元素中,<template> 几乎总是配合 attachShadow 使用,而不是插入到 light DOM。
原因很实际:
- 避免模板内样式污染全局(
<style>插入 light DOM 会全局生效) - 保证事件委托和选择器作用域可控
- shadow root 能真正隔离 template 克隆后的实例
- 现代框架(如 Lit)底层就是靠
template.content.cloneNode(true)+root.appendChild()实现渲染
容易忽略的一点:如果你把 template 内容克隆进 light DOM,又用了 class 名(比如 .card),那它就和页面其他同名 class 完全混在一起——没有封装,也没有复用优势。

