太好了,我们就用你上传的代码,把“从‘看网页’到‘做网页’”这篇文章(slug=post-2025-08-31-kekgcy)从首页 → 文章详情页的完整“路由流程”走一遍,并把关键代码逐行标注出来。你现在的首页是 SPA(单页应用) 风格的哈希路由:URL 形如 index.html#/post/<slug>,页面不刷新,只切换视图。
当首页渲染文章列表时,会给每篇文章生成一个指向哈希路由的链接:
<!-- script.js 第120–136行附近(生成卡片) -->
<a href="#/post/${a.slug}" class="stretched-link">阅读全文</a> <!-- 关键:点击只改变 hash -->
<!-- script.js 第147–153行附近(生成表格行) -->
<td><a href="#/post/${a.slug}">${titleCell}</a></td> <!-- 同样是 hash 链接 -->
作用:当你点击“从‘看网页’到‘做网页’”时,浏览器地址会变成 …/index.html#/post/post-2025-08-31-kekgcy,页面不刷新,只是 hash 改变。
页面启动时注册了路由器,并监听 hashchange:
// script.js 第330–332行
window.addEventListener("hashchange", router);
router(); // 首次进入页面时也跑一次
作用:无论是首次打开,还是点击文章导致 hash 变化,都会进入 router() 决定显示哪个视图。
// script.js 第280–287行
function parseHash() {
const hash = location.hash || "#/";
const m = hash.match(/^#\\/post\\/([\\w-]+)$/);
if (m) return { view: "post", slug: m[1] }; // 命中文章详情,提取 slug
if (hash.startsWith("#/contact")) return { view: "contact" };
if (hash.startsWith("#/demo")) return { view: "demo" };
return { view: "list" }; // 默认列表页
}
作用:当 hash 是 #/post/post-2025-08-31-kekgcy 时,解析结果为 { view: "post", slug: "post-2025-08-31-kekgcy" }。
// script.js 第314–321行
async function router() {
const { view, slug } = parseHash();
switch (view) {
case "post": await showDetailBySlug(slug); break; // 进入文章详情
case "contact": toContact(); break;
case "demo": toDemo(); break;
default: await renderList(); toList();
}
}