直接复制粘贴 nav 会导致多页面导航不同步,因代码重复且需手动修改每个文件;应抽离为 partials/nav.html 并用 fetch 动态加载,确保一次修改全站生效。

为什么直接复制粘贴 nav 会出问题
很多人改模板时,发现首页导航改了,但 products.html 和 about.html 里的导航还是旧的——不是忘了改,而是根本没同步。根源在于:这些页面是独立 HTML 文件,nav 代码重复写在每个文件里,改一处漏十处。更麻烦的是,一旦要加个新菜单项或换 logo 链接,就得手动打开七八个文件挨个找 <nav> 块替换,极易出错。
用 fetch() + insertAdjacentHTML 动态加载公共模块
不依赖构建工具、不改服务器配置,纯前端就能实现“一次写,全站用”。核心思路是:把 nav、footer 单独抽成 partials/nav.html 这样的纯 HTML 片段,再用 JS 在页面加载后自动注入。
-
partials/nav.html只放语义化结构,比如:<nav><ul><li><a href="index.html">首页</a></li></ul></nav>,不带任何样式或脚本 - 所有页面的
<body>里保留一个空容器:<div id="nav-placeholder"></div> - 在
js/main.js开头加一段加载逻辑:
fetch('partials/nav.html')
.then(res => res.text())
.then(html => {
document.getElementById('nav-placeholder').insertAdjacentHTML('beforeend', html);
});
注意:必须确保 fetch 调用发生在 DOM 加载完成后,否则 getElementById 找不到元素;若需兼容 IE,得换 XMLHttpRequest 或引入 polyfill。
include 语法不能直接用,但可以用服务端或构建时处理
有人看到 PHP 的 include 或 Jekyll 的 {% include %} 就想照搬,但在纯静态 HTML 模板里,浏览器根本不解析这些指令——它们是服务端或构建阶段才生效的。如果你用本地双击 index.html 方式预览,所有 include 语句都会原样显示为文本,甚至破坏页面结构。
立即学习“前端免费学习笔记(深入)”;
- 真要用
include类语法,必须走构建流程:比如用html-include插件配合 Parcel/Webpack,或用 Python 的html-includes工具做预编译 - 若部署到支持 PHP 的服务器(如大多数虚拟主机),可把
.html改成.php,然后用<?php include 'partials/nav.php'; ?>,但要注意 PHP 环境是否启用、路径是否相对当前文件 - GitHub Pages、Vercel 等静态托管平台不支持运行时服务端包含,强行写
include会直接报错或空白
抽离模块后,CSS 选择器作用域容易失控
原本写在 style.css 里的 nav ul li a 规则,在模块拆分后依然生效,但问题出在「谁该负责样式」变得模糊。比如你在 nav.html 里加了个 class="active",但 JS 没同步更新高亮逻辑,或者多个页面的 main.js 各自处理导航状态,结果首页高亮“产品”,点进产品页反而高亮“首页”。
- 建议把导航状态逻辑统一收口:用
window.location.pathname判断当前页面,动态给对应<li>加class="current",而不是靠 HTML 里硬编码 - CSS 中避免过度嵌套,例如不用
header nav ul li a:hover,改用.nav-link:hover这类语义类名,降低对 DOM 结构的强依赖 - 如果用了
fetch加载,注意 CSS 文件必须在<head>中提前引入,否则模块插入后样式可能闪动或失效
最常被忽略的其实是路径问题:当 products.html 和 index.html 不在同一级目录时,partials/nav.html 里的相对链接(如 href="contact.html")在子页面下会 404。解决方法是统一用根路径:href="/contact.html",或在 JS 加载前先修正所有 a 标签的 href 属性。



















