网站接入 Giscus 评论功能,显示评论数

纯静态网站或博客,由于没有数据存储功能,经常借助第三方的评论系统以插件的方式集成进来,而又以 Github 的 DiscussionsIssues 功能实现的居多。

  • giscus - 可借助组件库在 React、Vue 和 Svelte 中使用,支持多种语言
  • gitalk - 基于 Github Issue 和 Preact 开发的评论插件
  • utterances - 借助 Github issues 实现的轻量的评论组件,giscus 灵感就是来源于它

本站采用的是 Giscus 的方案。UI 风格我很喜欢,简介清爽。色调也和我的网站很搭。

Giscus 为 React、Vue、Solid 和 Svelte 都提供了对应的 组件库

这里以在 Docusaurus 中使用进行讲解:

安装

shell 复制代码
npm i @giscus/react

创建评论组件

接着我们以封装组件的形式,让评论功能成为我们网站代码的独立的一部分,在需要的地方引入即可。

jsx 复制代码
import React from 'react';
import Giscus from "@giscus/react";
import { useColorMode } from '@docusaurus/theme-common';

export default function GiscusComponent() {
  const { colorMode } = useColorMode();

  return (
    <div className="wrapper" id="Comment">
      <Giscus
        repo="fantingsheng/spacexcode-discus"
        repoId="R_kgDOJoGL9w"
        category="General"
        categoryId="DIC_kwDOJoGL984CWxiW"  // E.g. id of "General"
        mapping="url"                        // Important! To map comments to URL
        term="Welcome to @giscus/react component!"
        strict="0"
        reactionsEnabled="1"
        emitMetadata="1"
        inputPosition="top"
        theme={colorMode}
        lang="zh-Hans"
        loading="lazy"
        crossorigin="anonymous"
        async
      />
    </div>
  );
}

这里将常用到的一些特性说明下:

  1. 如果你想关闭它的懒加载,只需要将 loading="lazy" 这一项去掉即可;
  2. 关闭评论上方的表情回复,将 data-reactions-enabled="1" 参数设为 0
  3. 评论框的位置默认是放在评论的上方,这样在发表评论的时候就不必一定要滚动到底部,你可以通过 inputPosition 参数进行控制,它有两个值 topbottom

今天着重要讲的是一个功能是如何在你的页面中拿到评论数并显示?

显示评论数

一般的网站在标题的下面或者侧边栏都会有评论数的显示。而如果评论是以 Giscus 这样的外部插件的形式引入进来的,其实是通过 iframe 嵌入到当前网页的。数据是完全隔离开的。 那么我们还有没有办法拿到它的评论数据呢?

办法是有的!

官方的文档中也有提到 giscus-to-parent message events, 意思就是我们可以监听由 giscus 通过 window.parent.postMessage() 发送到父窗口的 message 事件。

官方给出的例子:

js 复制代码
function handleMessage(event: MessageEvent) {
  if (event.origin !== 'https://giscus.app') return;
  if (!(typeof event.data === 'object' && event.data.giscus)) return;

  const giscusData = event.data.giscus;
  // Do whatever you want with it, e.g. `console.log(giscusData)`.
  // You'll need to make sure that `giscusData` contains the message you're
  // expecting, e.g. by using `if ('discussion' in giscusData)`.
}

window.addEventListener('message', handleMessage);
// Some time later...
window.removeEventListener('message', handleMessage);

由此,我们很容易在网站的其它地方通过监听 message 事件来拿到评论的相关数据。

我们不妨先打印下,看返回来的数据结构是什么样:

jsx 复制代码
import useEventListener from '@site/src/hooks/useEventListener';

export default function Header () {
  useEventListener('message', function (e) {
    console.log(e);
  })

  return (
    // ...
  )
}

useEventListener 是我自己封装的事件监听的 hook,通过回调函数来处理相关逻辑。

我从打印的数据中截取了部分有用的数据,其中不难发现,data.giscus 是我们想要的数据。如果该篇文章下还没有任何的评论,那么它的值是 error,否则 就是一个对象,包含 totalCommentCounttotalReplyCount 两个字段。它们的和就是该文的总评论数。

然后我们完善后,完整的代码如下:

jsx 复制代码
import useEventListener from '@site/src/hooks/useEventListener';

export default function Header () {
  useEventListener('message', function (e) {
    console.log(e);
    if (e.origin !== 'https://giscus.app') return
    if (!(typeof e.data === 'object' && e.data.giscus)) return

    const giscus = e.data.giscus;

    if (giscus.error) {
      setCommentCounter(0)
      return
    }
    if (giscus.discussion) {
      setCommentCounter(
        giscus.discussion.totalCommentCount + giscus.discussion.totalReplyCount
      )
    }
  })

  return (
    // ...
  )
}

这里为了进入页面就要拿到评论数据,所以我们要关闭 Giscus 懒加载的配置选项。

好了,这篇文章就写到这里,感谢你的阅读。🥰

相关推荐
GISer_Jing3 分钟前
前端面试通关:Cesium+Three+React优化+TypeScript实战+ECharts性能方案
前端·react.js·面试
落霞的思绪1 小时前
CSS复习
前端·css
咖啡の猫3 小时前
Shell脚本-for循环应用案例
前端·chrome
百万蹄蹄向前冲5 小时前
Trae分析Phaser.js游戏《洋葱头捡星星》
前端·游戏开发·trae
朝阳5816 小时前
在浏览器端使用 xml2js 遇到的报错及解决方法
前端
GIS之路6 小时前
GeoTools 读取影像元数据
前端
ssshooter6 小时前
VSCode 自带的 TS 版本可能跟项目TS 版本不一样
前端·面试·typescript
Jerry7 小时前
Jetpack Compose 中的状态
前端
dae bal8 小时前
关于RSA和AES加密
前端·vue.js
柳杉8 小时前
使用three.js搭建3d隧道监测-2
前端·javascript·数据可视化