diff --git a/README.md b/README.md index 5bf2c8c..0e9fe8d 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ | 代码块 | Expressive Code(行号、折叠、语言徽章、自定义复制按钮) | | 数学公式 | remark-math + KaTeX | | 站内搜索 | Pagefind(构建时索引) | -| 页面切换 | Swup | +| 页面切换 | Astro View Transitions(``) | | 部署 | `./deploy.sh`(rsync 到树莓派 + 云服务器) | | 评论系统 | 自托管的 [twikoo](https://twikoo.js.org)(见下) | @@ -60,6 +60,7 @@ src/ ├── content/ Markdown 内容集合(见下) ├── data/ 站点配置:站点信息、个人信息、相册、评论、友链 ├── styles/ 全局 CSS +├── scripts/ 浏览器侧交互(lifecycle 契约,见下) ├── plugins/ 自定义 remark / rehype / Expressive Code 插件 ├── lib/ hooks/ 支撑逻辑 public/ 原样拷贝到产物根目录的静态资源 @@ -68,6 +69,34 @@ public/ 原样拷贝到产物根目录的静态资源 scripts/ 内容工具脚本 ``` +## 交互层 + +除了 React islands,站点还有一批「绑全局监听 / 操作 DOM」的原生脚本(主题切换、 +代码复制、github 卡片、灯箱、移动端菜单、评论、回到顶部)。它们都注册在 +`src/scripts/interactions.ts`,由 `src/layouts/BaseLayout.astro` 引一次。 + +因为页面切换走 ``(Astro View Transitions),DOM 每次导航都会被换掉, +而**模块脚本只会求值一次**。所以新增交互不要自己监听 `astro:page-load`、也不要用 +`window.__xxxBound` 防重复绑定,改用 `src/scripts/lifecycle.ts`: + +```ts +import { onPage } from "@/scripts/lifecycle" + +onPage("my-widget", () => { + const el = document.querySelector("[data-my-widget]") + if (!el) return // 本页没有这个组件:不挂载,也不报错 + const onClick = () => { /* ... */ } + el.addEventListener("click", onClick) + return () => el.removeEventListener("click", onClick) // astro:before-swap 时调用 +}) +``` + +`lifecycle` 在 `astro:before-swap` 卸载全部、在 `astro:page-load` 挂载全部, +并保证首屏、切页、模块重复求值这三种情况下都不会重复绑定或漏绑。 + +页面级的小交互如果**不需要 JS** 就别写 JS:阅读进度条和回到顶部按钮的显隐都由 +CSS 滚动驱动动画(`animation-timeline: scroll()`)负责,脚本只管点击与老浏览器降级。 + ## 写作 内容集合定义在 `src/content/config.ts`,共三个: diff --git a/src/components/ArticleContent.astro b/src/components/ArticleContent.astro index f227508..f887f0e 100644 --- a/src/components/ArticleContent.astro +++ b/src/components/ArticleContent.astro @@ -20,7 +20,7 @@ const primaryTag = tags[0] const primaryTagHref = primaryTag ? `/?tag=${encodeURIComponent(primaryTag)}#home-main` : null --- -
+
- -
diff --git a/src/components/ImageLightbox.astro b/src/components/ImageLightbox.astro index 05a25a2..cdbe744 100644 --- a/src/components/ImageLightbox.astro +++ b/src/components/ImageLightbox.astro @@ -8,6 +8,9 @@ * * 用事件委托 + 每次打开时重新收集当前页的图片,所以 ClientRouter 切页后依然有效; * 遮罩只在第一次点击时才创建,没点过就不占 DOM。 + * + * 监听器的挂载 / 摘除交给 src/scripts/lifecycle.ts(astro:before-swap 时卸载), + * 这里不再需要 `window.__vvLightboxBound` 那套防重复绑定的标记。 */ --- @@ -19,6 +22,7 @@ diff --git a/src/components/bookshelf-content.astro b/src/components/bookshelf-content.astro index a35c3c1..f8718c4 100644 --- a/src/components/bookshelf-content.astro +++ b/src/components/bookshelf-content.astro @@ -106,7 +106,7 @@ const recommendBadge = (status?: string) => {
-
+
diff --git a/src/components/pages/AboutPage.tsx b/src/components/pages/AboutPage.tsx index 97f86de..8cb0159 100644 --- a/src/components/pages/AboutPage.tsx +++ b/src/components/pages/AboutPage.tsx @@ -15,7 +15,7 @@ const journey = [ export default function AboutPage() { return (
-
+
{/* Hero Section */}
diff --git a/src/components/pages/FriendsPage.astro b/src/components/pages/FriendsPage.astro index c98cbdc..0575deb 100644 --- a/src/components/pages/FriendsPage.astro +++ b/src/components/pages/FriendsPage.astro @@ -52,7 +52,7 @@ const siteInfoText = [
-
+

diff --git a/src/components/site-header.astro b/src/components/site-header.astro index 24a9d7a..c24852f 100644 --- a/src/components/site-header.astro +++ b/src/components/site-header.astro @@ -268,19 +268,23 @@ const isCurrent = (href: string) => diff --git a/src/data/reading.json b/src/data/reading.json index b4df13d..b22ff30 100644 --- a/src/data/reading.json +++ b/src/data/reading.json @@ -1,5 +1,5 @@ { - "updatedAt": "2026-09-21T00:13:50.916Z", + "updatedAt": "2026-09-21T01:32:16.851Z", "source": "weread", "books": [ { diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index c366d31..40a7a99 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -176,28 +176,6 @@ const resolvedTwitterDescription = twitterDescription || description window.__applyTheme = applyTheme; })(); - - - diff --git a/src/pages/404.astro b/src/pages/404.astro index f6be339..fb1a2fc 100644 --- a/src/pages/404.astro +++ b/src/pages/404.astro @@ -35,7 +35,7 @@ const entries = [
-
+

404

diff --git a/src/pages/[...page].astro b/src/pages/[...page].astro index 2c7c6a2..f543ee3 100644 --- a/src/pages/[...page].astro +++ b/src/pages/[...page].astro @@ -31,7 +31,7 @@ const title =
-
+
{/* 同 index.astro:手机端落点贴页眉下沿(列表开头是吸顶胶囊条),lg 以上保留呼吸位 */}
-
+
{/* 封面横幅 */}
{cover ? ( diff --git a/src/pages/gallery/index.astro b/src/pages/gallery/index.astro index dc183f1..95ff997 100644 --- a/src/pages/gallery/index.astro +++ b/src/pages/gallery/index.astro @@ -15,7 +15,7 @@ const allTags = getAllAlbumTags(albums)
-
+
{/* 页头 */}
diff --git a/src/pages/index.astro b/src/pages/index.astro index c342ea1..881ac34 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -21,7 +21,7 @@ const thoughtPreviews = thoughts.map((thought) => toThoughtPreview(thought)).sli
-
+
{/* 手机端锚点落点要贴页眉下沿:这一屏列表的第一个元素是吸顶胶囊条 diff --git a/src/pages/studies/[id].astro b/src/pages/studies/[id].astro index e605ac6..b80cc89 100644 --- a/src/pages/studies/[id].astro +++ b/src/pages/studies/[id].astro @@ -20,7 +20,7 @@ const description = study.epigraph ?? ""
-
+