
本文介绍一种无需服务器端语言(如 php)或构建工具,仅用原生 javascript 和 html 实现页眉/页脚复用的方法,适用于静态网站(.html 文件),通过 fetch 动态加载外部 html 片段并注入 dom。
本文介绍一种无需服务器端语言(如 php)或构建工具,仅用原生 javascript 和 html 实现页眉/页脚复用的方法,适用于静态网站(.html 文件),通过 fetch 动态加载外部 html 片段并注入 dom。
在开发多页面静态网站(如影院管理系统)时,页眉(Header)和页脚(Footer)通常在每个页面重复出现。若直接复制粘贴 HTML 代码,后期维护成本极高——一处修改需同步更新所有页面。理想方案是将公共结构抽离为独立文件(如 header.html),再按需“插入”到各页面中。但标准 HTML 不支持原生 include,且 <link rel="import"> 已被废弃,PHP 又受限于 .html 后缀无法执行。此时,客户端 JavaScript 动态加载成为最轻量、兼容性好、零依赖的解决方案。
✅ 推荐实现方式:Fetch + innerHTML
核心思路:在目标页面预留一个容器元素(如 <div id="header-placeholder">),通过 fetch() 请求外部 HTML 文件,获取文本后注入该容器。
1. 创建独立的页眉文件(header.html)
注意:该文件仅包含 HTML 片段,不包含 <html>、<head> 或 <body> 标签,避免嵌套结构冲突:
<!-- header.html -->
<nav class="navigation-open">
<div class="global container grid-x">
<div class="logowrapper grid-x">
<div class="logo-container">
<a href="index.html">
<img class="logo" src="../img/logo.png" alt="Cate Cinema Logo">
</a>
</div>
</div>
<div class="dashboard-nav cell grid-x">
<nav class="choicewrapper">
<ul class="wrapper">
<li class="page-cinema">
<a href="#" class="gradient-fill-hover">
<span>A</span><span>l</span><span> </span><span>C</span><span>i</span><span>n</span><span>e</span><span>m</span><span>a</span>
</a>
</li>
<!-- 其他导航项保持不变 -->
</ul>
</nav>
</div>
<nav class="loginwrapper grid-x cell align-right">
<!-- 登录区域代码 -->
</nav>
</div>
</nav>2. 在主页面中声明占位符并加载页眉
在任意 .html 页面的 <body> 中,插入占位容器,并在页面底部(确保 DOM 加载完成)执行加载逻辑:
立即学习“前端免费学习笔记(深入)”;
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Cate Cinema</title>
<!-- 所有 CSS 链接(字体、样式表等) -->
</head>
<body id="homepage">
<!-- 页眉占位符 -->
<div id="header-placeholder"></div>
<!-- 主要内容区域 -->
<main id="content">
<h1>Welcome to Cate Cinema</h1>
<!-- 页面具体内容 -->
</main>
<!-- 脚本:在 DOM 就绪后加载页眉 -->
<script>
document.addEventListener('DOMContentLoaded', () => {
fetch('./header/header.html') // 路径需与实际位置匹配
.then(response => {
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
return response.text();
})
.then(data => {
document.getElementById('header-placeholder').innerHTML = data;
// ⚠️ 注意:动态注入的 HTML 中的事件监听器需重新绑定
// 例如:登录下拉菜单交互、搜索提交等,应在 data 插入后初始化
initHeaderInteractions();
})
.catch(err => console.error('Failed to load header:', err));
});
function initHeaderInteractions() {
// 示例:为登录按钮添加点击展开逻辑
const loginToggle = document.querySelector('.profile-login > a');
const dropdown = document.querySelector('.container-login');
if (loginToggle && dropdown) {
loginToggle.addEventListener('click', (e) => {
e.preventDefault();
dropdown.classList.toggle('open');
});
}
}
</script>
</body>
</html>? 关键注意事项
- 路径问题:fetch() 的路径是相对于当前 HTML 文件的 URL,建议使用相对路径(如 ./header/header.html)并确保路径正确。
- CORS 限制:若直接双击打开本地 HTML 文件(file:// 协议),浏览器会因跨域策略拒绝 fetch 请求。必须通过本地服务器运行(如 VS Code 的 Live Server 插件、Python 的 python -m http.server),否则将报错。
- 脚本与样式隔离:header.html 中不应包含 <script> 或 <style> 标签——所有 JS 逻辑应在主页面统一管理;CSS 应通过主页面 <link> 引入,确保全局生效。
- SEO 与可访问性:动态加载的内容对搜索引擎爬虫可能不友好(取决于爬虫能力),且初始 HTML 源码中无页眉结构。如需强 SEO 支持,建议改用服务端渲染或静态站点生成器(如 Jekyll、Hugo)。
- 错误处理:务必添加 .catch() 捕获网络失败或 404 错误,并提供降级方案(如显示默认提示)。
✅ 总结
对于纯静态 HTML 项目,fetch() + innerHTML 是目前最实用、标准、无构建依赖的页眉/页脚复用方案。它平衡了开发效率与部署简易性,特别适合中小型项目或原型开发。只要确保运行环境为 HTTP 服务、路径配置准确、交互逻辑妥善初始化,即可安全稳定地实现组件化布局。后续如项目规模扩大,再平滑迁移到 Web Components、模板引擎或现代前端框架亦十分自然。



















