整站统一靠可注入、可继承、可隔离的结构控制机制实现,而非复制粘贴;Web Components 和构建时预处理最可靠,<template>+JS 是需守边界的折中方案。

整站统一不是靠“复制粘贴模板文件”实现的,而是靠一种可注入、可继承、可隔离的结构控制机制。直接在每个页面里写重复的 <header> 和 <footer>,等于把统一性交给了人力,迟早崩。
用 <template> + JS 实例化做轻量级统一
适合静态站点、无构建流程、需快速落地的场景。核心是把公共结构藏进 <template>,再用 JS 按需克隆填充。
- 必须用
document.importNode(template.content, true)而非cloneNode(true),否则表单元素、<select>的状态可能丢失 - 模板内避免硬编码内容,改用
data-bind="title"或class="js-title"这类标记,由 JS 统一注入 - 不要在
DOMContentLoaded之前操作template.content,它此时可能还没解析完成 - 示例:加载页脚时,先查
document.getElementById('footer-template'),再importNode,最后appendChild到document.querySelector('footer')
用 Web Components 实现真正封装的统一
这是唯一能让 <site-header> 和 <site-footer> 成为语义化、样式隔离、行为自治单元的方式。不是“复用代码”,而是“复用能力”。
- 必须在
constructor()中调用super(),漏掉会报Failed to construct 'CustomElement': Please use the 'new' operator - DOM 操作不能放在
constructor,要等connectedCallback—— 此时元素才挂载到文档中 - 若需响应属性变化(如
<site-header title="首页">),得定义static get observedAttributes()并实现attributeChangedCallback - Shadow DOM 内部不能用外部 CSS,所有样式必须内联或通过
<style>注入到this.shadowRoot
用构建时预处理保证上线即统一
如果你用 Vite、Webpack 或 Hugo/Jekyll 这类工具,就别在浏览器里拼 HTML。构建阶段合并,输出就是完整 HTML,零运行时开销,SEO 友好,CDN 缓存也最稳。
立即学习“前端免费学习笔记(深入)”;
- Vite 用户可用
vite-plugin-html,在index.html里写<!-- @include ./components/header.html --> - Webpack 用户配合
html-loader+html-webpack-plugin,支持require('./header.html')式导入 - 注意路径问题:
./components/header.html是相对构建配置的根目录,不是相对于当前 HTML 文件 - 不推荐用 SSI(
<!--#include file="header.html" -->)做全站统一——它依赖服务器配置,本地开发无法预览,且无法传参或条件渲染
真正难的不是“怎么让页头出现在每个页面”,而是“当设计改了字体大小、导航加了新菜单项、页脚要动态显示版权年份时,你改几处就能全站生效”。答案不在某个技术点,而在你选的方案是否支持数据驱动、是否允许局部更新、是否阻断样式泄漏。Web Components 和构建时预处理在这三点上最可靠;<template> + JS 是折中选择,但必须守住“只负责结构,不掺逻辑”的边界。



















