必须用document.importNode(tmpl.content, true)安全克隆<template>内容,它能保留表单状态、select选中项、checkbox checked态及Shadow DOM兼容性;innerHTML或cloneNode(true)会丢失这些原生行为。
document.importNode() 安全克隆 <template> 内容直接 innerHTML = template.innerHTML 或 cloneNode(true) 会丢掉表单状态、<select> 选中项、<input type="checkbox"> 的 checked 状态,甚至在 Shadow DOM 场景下失效。必须用 document.importNode(tmpl.content, true) —— 它才是真正保留 DOM 行为语义的克隆方式。
DOMContentLoaded 前读取 tmpl.content,否则拿到空 DocumentFragmenttmpl 引用,避免反复 getElementById
importNode 返回的是 DocumentFragment,可直接 appendChild 到目标容器,不触发重排<template> 支持传参和动态填充纯 <template> 没有属性绑定或响应式机制,“传参”本质是 JS 工厂函数接收对象,再手动映射到节点。它不是 Vue 的 v-bind,而是显式查找 + 替换。
data-bind="title" 这类语义化标记,比 class="js-title" 更易维护、不易被样式类误删textContent(防 XSS),HTML 片段才用 innerHTML,且需确保来源可信id="card-1" —— 多次实例化会导致 ID 冲突,影响 querySelector 和 label 关联textContent 或 dataset 值innerHTML 直接注入第三方 HTML 片段直接 container.innerHTML = fetchedHtml 是最常见也最危险的做法:样式泄漏、脚本执行失控、ID 冲突、XSS 风险全部集中爆发。尤其当片段含 <style> 或第三方 CSS 类名(如 .button)时,极易覆盖宿主页面全局样式。
shadowRoot
<script> 不会自动执行,需手动 eval 或创建 script 元素并 append,但有 CSP 风险eval 或启用了严格 CSP,动态脚本注入基本不可行本地开发能跑通、上线就错,往往是因为依赖运行时 fetch —— 而构建时合并 HTML 片段,输出即完整 HTML,零运行时开销,SEO 友好,CDN 缓存也最有效。
立即学习“前端免费学习笔记(深入)”;
vite-plugin-html,支持 <!-- @include ./components/header.html --> 语法html-loader + html-webpack-plugin,可用 require('./header.html') 导入vite.config.js 或 webpack.config.js 所在位置),不是相对于当前 .html 文件<!--#include file="header.html" -->)—— 本地无法预览,也无法传参或做条件渲染真正难的不是“把 header 插进去”,而是“header 里的 logo 路径变了、菜单加了新项、版权年要自动更新到 2026 年 6 月 30 日”——这些逻辑必须落在数据层或构建流程里,而不是靠人肉改 HTML。