Skip to content

VitePress 使用 Gitalk 添加评论功能

前言

一个优质的博客怎么能没有评论功能呢?但看来看去,不用自己搭建后端服务的方案都大同小异,都是利用 Githubissues 模块实现的。

其中的佼佼者是 GitmentGitalk ,只可惜这两个库是难兄难弟,基本上都停更了。

Gitment 最后更新日期为 2018.04.05, Gitalk 最后更新日期为 2022.07.18。

最后还是确定使用 Gitalk ,引用了大神 @lesonky 修改以后的 Gitalk 库,参考了博客《vitepress 配置评论(gitalk)》

环境

node: v16.15.1

Gitalk: v1.7.2

实现

注册 OAuth

这一步是为了使用 Github 提供的 OAuth2(第三方登录服务)。

1. 来到 Github Application 创建页面

2. 配置参数注册 OAuth

3. 查看生成的 Client IDClient secrets

安装 Gitalk

根据上文博客评论区大神的说法,还是推荐直接从 Github 安装 Gitalk

因为我一直安装不成功大神的库,所以我直接 fork 了大神 Gitalk 仓库,把地址改成了自己的仓库地址,你们也可以直接用我的。

具体配置如下

json
"devDependencies": {
  "gitalk": "https://github.com/LibraHeresy/gitalk.git",
  "vitepress": "^1.0.0-alpha.72"
},

然后npm直接安装就行了。

挂载 Gitalk 组件

docs/.vitepress 路径下,新建 theme 文件夹,在该文件夹下新建 index.jsMyLayout.vue

index.js

index.js 文件内导入 VitePress 默认主题配置,再导入自己写的布局组件,覆盖默认主题对象的 Layout 属性,最后导出该文件。

js
import DefaultTheme from "vitepress/theme";
import MyLayout from "./MyLayout.vue";

export default {
  ...DefaultTheme,
  Layout: MyLayout,
};

MyLayout.vue

这里和上文的博客说法完全不一样,折腾了很久才知道,VitePress 有一个默认的 Layout 组件, Layout 组件内有负责渲染文本的 Content 组件,我们需要的只是在 Layout 组件上挂载一个评论组件而已。

但是按照博客的写法,不出意外我们只能收获一个只有评论组件的页面,所以就要导入原有的 Layout 组件,并使用 Vue3 的新写法,直接写一个子组件渲染挂载评论组件到 Layout 组件上。

html
<template>
  <Layout />
</template>

<script setup>
  import DefaultTheme from "vitepress/theme";
  const { Layout } = DefaultTheme;
  import { watch, nextTick, onMounted } from "vue";
  import "gitalk/dist/gitalk.css";
  import Gitalk from "gitalk";
  import { useRouter } from "vitepress";

  let { route } = useRouter(); // 页面路由对象

  onMounted(() => {
    watch(
      () => route.path, // 监听路由变化,重新挂载评论组件
      () => {
        nextTick(() => {
          if (typeof window !== undefined) {
            const content_div = document.querySelector(".content-container"); // 查找页面内容DOM节点,此节点只有layout为Page(默认layout属性)的md文档才有
            if (content_div) {
              const before_s_div = document.getElementById("gitalk-page-container") // 获取页面评论组件DOM节点
              if(before_s_div) { 判断是否已有评论组件节点,有则删除,重新创建。
                content_div.removeChild(before_s_div)
              }
              const s_div = document.createElement("div"); // 创建节点
              s_div.setAttribute("id", "gitalk-page-container"); // 设置id
              content_div.appendChild(s_div); // querySelector的节点可自己根据自己想加载的地方设置
              const gitment = new Gitalk({
                id: route.data.title, // 可选,推荐设置为页面标题,因为会作为标签传给Github issues,且issues标签有长度限制。
                owner: "LibraHeresy", // GitHub repository 所有者
                repo: "vite-press", // GitHub repository
                clientID: "", // 自己的clientID
                clientSecret: "", // 自己的clientSecret
                admin: ["LibraHeresy"], // GitHub repository 所有者
                labels: ["Gitalk"], // GitHub issue 的标签
                createIssueManually: false, //如果当前页面没有相应的 isssue 且登录的用户属于 admin,则会自动创建 issue。如果设置为 true,则显示一个初始化页面,创建 issue 需要点击 init 按钮。
              });
              gitment.render("gitalk-page-container");
            }
          }
        })
      },
      { immediate: true }
    );
  });
</script>

全部配置好,就可以收获一个有评论功能的博客了。

遇到的问题

打包报错,提示找不到 windowdocument 对象

因为在打包的时候,项目处于 node 环境,当然就没有 windowdocument 对象,所以和两个对象有关的方法要放在 onMounted 生命周期方法内,这是 VitePress 的规则。

切换首页后,评论组件消失

这是因为当你首页设置 layouthome 时,页面是没有 .content-container 节点的,所以评论组件会和 .content-container 这个节点一起被删除。

而当你切回博客页面时,挂载方法是写在 onMounted 生命周期方法内,也不会再挂载评论组件了。

这个时候我们要用 watch 函数监听路由变化,重新执行挂载方法。

切换页面后,评论组件没有刷新

这是因为页面本身没有变化,变得只是 Content 组件渲染的文本内容而已,原因是 SPA

所以我们需要手动删除原有的评论组件 DOM 节点,重新挂载一个新的评论组件。

Released under the MIT License.