Skip to content

给 Astro 增加留言回复功能

发布于: at 02:00

内容目录

可选方案

在 2024 年给静态博客添加评论系统的可选方案已有很多。本文选择依赖 GitHub Discussion 的方案 giscus。

giscus 的配置方法请参见官方文档 https://giscus.app/zh-CN

实现方式

在 Astro 中,使用 giscus 的方法是:在官方获得你的 script 代码段后,插入到 src/layouts/PostDetails.astro 中的 </main> 前。

  <main>

    ...

    <script src="https://giscus.app/client.js"
        data-repo="[ENTER REPO HERE]"

        ...

    </script>
  </main>

组件化

组件化是一种将页面中重复的代码片段提取出来,以组件的形式进行封装,方便代码复用的方式。

此时,我们先运行

npm i @giscus/react

然后在组件目录 src/components 创建一个 Comments.tsx 的 React 组件:

源码请见 Comments.tsx

import Giscus, { type Theme } from "@giscus/react";
import { GISCUS } from "@config";
import { useEffect, useState } from "react";

interface CommentsProps {
  lightTheme?: Theme;
  darkTheme?: Theme;
}

export default function Comments({
  lightTheme = "light",
  darkTheme = "dark",
}: CommentsProps) {
  const [theme, setTheme] = useState(() => {
    const currentTheme = localStorage.getItem("theme");
    const browserTheme = window.matchMedia("(prefers-color-scheme: dark)")
      .matches
      ? "dark"
      : "light";

    return currentTheme || browserTheme;
  });

  useEffect(() => {
    const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
    const handleChange = ({ matches }: MediaQueryListEvent) => {
      setTheme(matches ? "dark" : "light");
    };

    mediaQuery.addEventListener("change", handleChange);

    return () => mediaQuery.removeEventListener("change", handleChange);
  }, []);

  useEffect(() => {
    const themeButton = document.querySelector("#theme-btn");
    const handleClick = () => {
      setTheme(prevTheme => (prevTheme === "dark" ? "light" : "dark"));
    };

    themeButton?.addEventListener("click", handleClick);

    return () => themeButton?.removeEventListener("click", handleClick);
  }, []);

  return (
    <div className="mt-8">
      <Giscus theme={theme === "light" ? lightTheme : darkTheme} {...GISCUS} />
    </div>
  );
}

并在 src/config.ts 加入

import type { GiscusProps } from "@giscus/react";
export const GISCUS: GiscusProps = {
  repo: "[ENTER REPO HERE]",
  repoId: "[ENTER REPO ID HERE]",
  category: "[ENTER CATEGORY NAME HERE]",
  categoryId: "[ENTER CATEGORY ID HERE]",
  mapping: "pathname",
  reactionsEnabled: "0",
  emitMetadata: "0",
  inputPosition: "bottom",
  lang: "en",
  loading: "lazy",
};

最后,替换刚才 </main> 前的 script 标签。

  <main>

    ...

    <Comments client:only />

  </main>

至此,你已按 Astro 的方式添加了 giscue 评论系统。