前言
一个优质的博客怎么能没有评论功能呢,没有评论怎么和同志们的思想激情 ♂ 碰撞,获得新的收获。
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
仓库,把地址改成了自己的仓库地址,你们也可以直接用我的。
具体配置如下
"devDependencies": {
"gitalk": "https://github.com/LibraHeresy/gitalk.git",
"vitepress": "^1.0.0-alpha.72"
},
然后npm
直接安装就行了。
挂载 Gitalk 组件
在 docs/.vitepress
路径下,新建 theme
文件夹,在该文件夹下新建 index.js
和 MyLayout.vue
。
index.js
在 index.js
文件内导入 VitePress
默认主题配置,再导入自己写的布局组件,覆盖默认主题对象的 Layout
属性,最后导出该文件。
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
组件上。
<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>
全部配置好,就可以收获一个有评论功能的博客了。
遇到的问题
打包报错,提示找不到 window
和 document
对象
因为在打包的时候,项目处于 node
环境,当然就没有 window
和 document
对象,所以和两个对象有关的方法要放在 onMounted
生命周期方法内,这是 VitePress
的规则。
切换首页后评论组件消失
这是因为当你首页设置layout
为home
时,页面是没有 .content-container
节点的,所以评论组件会和.content-container
这个节点一起被删除。
而当你切回博客页面时,挂载方法是写在 onMounted
生命周期方法内,也不会再挂载评论组件了。
这个时候我们要用 watch
函数监听路由变化,重新执行挂载方法。
切换页面评论组件没有刷新
这是因为页面本身没有变化,变得只是 Content
组件渲染的文本内容而已,原因是 Vue
的 SPA
模式。
所以我们需要手动删除原有的评论组件 DOM
节点,重新挂载一个新的评论组件。