前言
一个优质的博客怎么能没有评论功能呢,没有评论怎么和同志们的思想激情 ♂ 碰撞,获得新的收获。
Ah, That's good.
那么用什么方案呢,看来看去,不用自己搭建后端服务的方案都大同小异,都是利用 Github 的 issues 模块实现的。
其中的佼佼者是 Gitment 和 Gitalk ,只可惜这两个库是难兄难弟,基本上都停更了。
Gitment 最后更新日期为 2018.04.05, Gitalk 最后更新日期为 2022.07.18。
最后还是确定使用 Gitalk ,引用了大神 @lesonky 修改以后的 Gitalk 库,参考了博客《vitepress 配置评论(gitalk)》。
环境
node: 16.15.1
Gitalk: 1.7.2
实现
注册 OAuth
这一步是为了使用 Github 提供的 OAuth2(第三方登录服务)。
1. 来到 Github Application 创建页面

2. 配置参数注册 OAuth


3. 查看生成的 Client ID 和 Client secrets


安装 Gitalk
根据上文博客评论区大神的说法,还是推荐直接从 Github 安装 Gitalk 。
因为我一直安装不成功大神的库,所以我直接 fork 了大神 Gitalk 仓库,把地址改成了自己的仓库地址,你们也可以直接用我的。
具体配置如下
1"devDependencies": { 2 "gitalk": "https://github.com/LibraHeresy/gitalk.git", 3 "vitepress": "^1.0.0-alpha.72" 4},
然后npm直接安装就行了。
挂载 Gitalk 组件
在 docs/.vitepress 路径下,新建 theme 文件夹,在该文件夹下新建 index.js 和 MyLayout.vue 。
index.js
在 index.js 文件内导入 VitePress 默认主题配置,再导入自己写的布局组件,覆盖默认主题对象的 Layout 属性,最后导出该文件。
1import DefaultTheme from "vitepress/theme"; 2import MyLayout from "./MyLayout.vue"; 3 4export default { 5 ...DefaultTheme, 6 Layout: MyLayout, 7};
MyLayout.vue
这里和上文的博客说法完全不一样,折腾了很久才知道,VitePress 有一个默认的 Layout 组件, Layout 组件内有负责渲染文本的 Content 组件,我们需要的只是在 Layout 组件上挂载一个评论组件而已。
但是按照博客的写法,不出意外我们只能收获一个只有评论组件的页面,所以就要导入原有的 Layout 组件,并使用 Vue3 的新写法,直接写一个子组件渲染挂载评论组件到 Layout 组件上。
1<template> 2 <Layout /> 3</template> 4 5<script setup> 6import DefaultTheme from "vitepress/theme"; 7const { Layout } = DefaultTheme; 8import { watch, nextTick, onMounted } from "vue"; 9import "gitalk/dist/gitalk.css"; 10import Gitalk from "gitalk"; 11import { useRouter } from "vitepress"; 12 13let { route } = useRouter(); // 页面路由对象 14 15onMounted(() => { 16 watch( 17 () => route.path, // 监听路由变化,重新挂载评论组件 18 () => { 19 nextTick(() => { 20 if (typeof window !== undefined) { 21 const content_div = document.querySelector(".content-container"); // 查找页面内容DOM节点,此节点只有layout为Page(默认layout属性)的md文档才有 22 if (content_div) { 23 const before_s_div = document.getElementById("gitalk-page-container") // 获取页面评论组件DOM节点 24 if(before_s_div) { 判断是否已有评论组件节点,有则删除,重新创建。 25 content_div.removeChild(before_s_div) 26 } 27 const s_div = document.createElement("div"); // 创建节点 28 s_div.setAttribute("id", "gitalk-page-container"); // 设置id 29 content_div.appendChild(s_div); // querySelector的节点可自己根据自己想加载的地方设置 30 const gitment = new Gitalk({ 31 id: route.data.title, // 可选,推荐设置为页面标题,因为会作为标签传给Github issues,且issues标签有长度限制。 32 owner: "LibraHeresy", // GitHub repository 所有者 33 repo: "vite-press", // GitHub repository 34 clientID: "", // 自己的clientID 35 clientSecret: "", // 自己的clientSecret 36 admin: ["LibraHeresy"], // GitHub repository 所有者 37 labels: ["Gitalk"], // GitHub issue 的标签 38 createIssueManually: false, //如果当前页面没有相应的 isssue 且登录的用户属于 admin,则会自动创建 issue。如果设置为 true,则显示一个初始化页面,创建 issue 需要点击 init 按钮。 39 }); 40 gitment.render("gitalk-page-container"); 41 } 42 } 43 }) 44 }, 45 { immediate: true } 46 ); 47}); 48</script>
全部配置好,就可以收获一个有评论功能的博客了。

遇到的问题
打包报错,提示找不到 window 和 document 对象
因为在打包的时候,项目处于 node 环境,当然就没有 window 和 document 对象,所以和两个对象有关的方法要放在 onMounted 生命周期方法内,这是 VitePress 的规则。
切换首页后评论组件消失
这是因为当你首页设置layout为home时,页面是没有 .content-container 节点的,所以评论组件会和.content-container这个节点一起被删除。
而当你切回博客页面时,挂载方法是写在 onMounted 生命周期方法内,也不会再挂载评论组件了。
这个时候我们要用 watch 函数监听路由变化,重新执行挂载方法。
切换页面评论组件没有刷新
这是因为页面本身没有变化,变得只是 Content 组件渲染的文本内容而已,原因是 Vue 的 SPA 模式。
所以我们需要手动删除原有的评论组件 DOM 节点,重新挂载一个新的评论组件。
