原生 标签仅作离线容器,不支持条件/循环渲染;其内容需通过 template.content 访问,克隆后手动填充并批量插入 fragment 以避免重排,data- 属性保留但需手动提取, 无效,所有路径、样式、事件均需重新处理。

原生 <template></template> 标签不支持条件或循环渲染——它只是个离线容器,所有逻辑必须靠 JS 手动实现。 想用它替代 Vue 的 v-if 或 v-for,直接写 HTML 语法会完全失效。
为什么 template.innerHTML 总是空字符串?
因为 <template></template> 的内容被浏览器解析为文档片段(DocumentFragment),不参与主 DOM 树,也不暴露在 innerHTML 中。直接读取会得到空值。
- 必须用
template.content访问其内部节点,这是唯一合法入口 -
content是只读的DocumentFragment,不能直接修改,得先cloneNode(true) - 若模板里有
<script></script>或<style></style>,克隆后不会执行脚本、也不会重复注入样式
手动实现循环渲染:克隆 + 填值 + 批量插入
核心是避免反复操作真实 DOM。每轮 appendChild 都触发重排,列表一过百条就卡顿。
- 用
document.createDocumentFragment()创建轻量中间容器 - 循环中:调用
template.content.cloneNode(true)→ 用querySelector找目标元素 → 改textContent或value(别用innerHTML,防 XSS 且不保留事件监听器) - 把克隆好的节点塞进
frag,最后一次性container.appendChild(frag) - 每次循环都必须
cloneNode(true),否则所有项共用同一节点引用,数据会覆盖
data- 属性和 <slot></slot> 在克隆后是否可用?
能保留但不“激活”——它们只是静态属性,不会自动映射为 JS 数据,也不触发 Shadow DOM 行为。
-
data-id会被克隆保留,但你得自己用element.dataset.id提取,它不会变成对象字段 -
<slot name="title"></slot>在普通<template></template>中完全无效:没有shadowRoot,slot不被解析,querySelector('[slot="title"]')查不到东西 - 想做内容分发,得自己约定结构,比如用
class="slot-title"替代slot语义
最易被忽略的是:克隆后的节点脱离原始模板上下文,所有相对路径、CSS 作用域、事件绑定都要重新处理;template 不是魔法,它只提供结构复用能力,其余全是手写逻辑的活儿。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











