HTML模板需通过template.content.cloneNode(true)克隆使用,直接操作innerHTML或appendChild(template)无效;构建时模板(如Vite插件)比运行时JS更稳定、SEO友好。
HTML 模板本身不强制要求内容复用,但一旦你有多个页面共享导航、卡片、表单等结构,就立刻需要它——原生 HTML 文件不支持 include、不能传参、无法条件渲染,硬写死结构只会让维护成本指数级上升。
很多人把 header.html 复制到 10 个页面里,改一个 class 名就得手动搜 10 次。更糟的是:
template.content.firstChild 常是空白文本,直接 appendChild 会插入不可见字符innerHTML 会触发 XSS,而 cloneNode + textContent 天然免疫<template> 标签必须配合 content.cloneNode(true) 才能用<template> 不是“写完就能用”的模板,它只是浏览器跳过的占位容器。常见错误是把它当普通 DOM:
template.innerHTML 永远是空字符串,取不到内容document.body.appendChild(template) 什么也不会渲染template.content → cloneNode(true) → 填充数据 → 插入真实 DOM<slot>,独立使用时会被忽略;只有在自定义元素中才生效示例:
立即学习“前端免费学习笔记(深入)”;
<template id="card"> <article class="card"> <h3 class="card-title"></h3> <p class="card-desc"></p> </article></template><script>const tmpl = document.querySelector('#card');const instance = tmpl.content.cloneNode(true); // 必须 cloneinstance.querySelector('.card-title').textContent = '标题';document.body.appendChild(instance);</script>
真正稳定的内容复用,发生在构建时,而非运行时:
vite-plugin-html 或 html-webpack-plugin 支持 template + data 注入,编译后生成纯 HTML,SEO 友好、无 JS 依赖<% include('nav') %> 是服务端逻辑,复用靠文件引用,不是靠 DOM 操作<slot>、Hugo 的 {{ define "main" }},本质是编译期结构分发,不是运行时克隆<slot> 不自动绑定数据,仍需 JS 配合最容易被忽略的一点:复用是否成立,不取决于你用了 <template> 还是 include,而在于路径是否统一、作用域是否隔离、数据生命周期是否可控——三者错一个,所谓“复用”就退化成多处同步修改的幻觉。