什么是 Twikoo
Twikoo是一个简洁、安全、免费的静态网站评论系统,能够为个人博客等站点提供优质的评论体验,并能够对评论进行便捷的管理。
为 Fuwari 接入 Twikoo
我们先在项目目录src/components/comment下创建文件Twikoo.astro文件,它代表着 Twikoo 组件,在这里我们使用 Twikoo 官方文档中的「通过 CDN 引入」方式。如同Fuwari-PR-37所做的那样。
<script is:inline src="https://cdn.staticfile.org/twikoo/1.6.32/twikoo.all.min.js"></script><script is:inline define:vars="{{" config }}> twikoo.init(config);</script>但这种方式存在一个问题,若twikoo.all.min.js未加载完成,但程序已经执行到了twikoo.init(config),这将会导致一种错误。

显然,当远程文件未加载完成时,将会概率触发这个问题,未加载完成时就调用twikoo.all.min.js将会导致twikoo未定义,因此,我们应该在twikoo.all.min.js加载完成后,再执行init方法。即这篇文章所讲诉的方法。
<div id="comment"></div><script> function loadTwikoo() { const script = document.createElement("script"); script.src = "https://cdn.jsdelivr.net/npm/twikoo@1.6.41/dist/twikoo.all.min.js"; script.defer = true; script.onload = () => { twikoo.init(); //在这里传入你的Twikoo配置信息 }; document.body.appendChild(script); }</script><!--Twikoo.astro-->但这种方式似乎仍然不够完善,在这种情况下,评论组件仍然会偶现无法加载。这是由于 Fuwari 使用了swup来确保类似单页应用的平滑过渡体验,在使用swup后,JavaScript脚本并不会在每次都被重新加载,这将会导致虽然没有上述的错误,但评论组件仍然会无法正常显示。
要解决这种情况,我们可以使用swup组件库中的hooks,在swup的特定的生命周期时,hooks内的函数将会被触发并调用。因此我们可以通过hooks手动通知组件重载评论区组件。Fuwari 的hooks处理部分的函数在src/layouts/Layout.astro中,我们可以把新添加的代码书写在这里。
function initCommentComponent() { const event = new Event("loadComment"); document.dispatchEvent(event);}在这里我们新建了一个函数,专用于创建loadComment的事件,即通知评论组件进行一次加载。
在Layout.astro的function init()函数内,需要添加对initCommentComponent()函数的一次调用,这样在打开网页时我们的评论将会被正确加载。
function init() { // disableAnimation()() // TODO loadTheme(); loadHue(); initCustomScrollbar(); initCommentComponent(); showBanner();}随后紧接着我们还需要在swup的hooks部分,添加对这个函数的调用。如Swup 文档所述,使用content:replace,这部分的函数将会在「页面的旧内容被新内容代替」时调用。我们可以紧接已存在的content:replace函数进行调用。
window.swup.hooks.on("content:replace", () => { initCustomScrollbar(); initCommentComponent();});在此,我们完成了对事件的传递。在Twikoo.astro中我们还要对事件进行监听,对Twikoo.astro完善后如下文所示。
---interface Props { path: string;}
const config = { el: "#comment", path: Astro.props.path,};---
<!-- 简化了配置部分的代码,实际上可以把配置文件统一写入fuwari的配置文件统一读取 --><div id="comment"></div><script define:vars={{ config }}> function loadTwikoo() { const script = document.createElement("script"); script.src = "https://cdn.jsdelivr.net/npm/twikoo@1.6.41/dist/twikoo.all.min.js"; script.defer = true; script.onload = () => { twikoo.init({ ...config, envId: "", // 你的envId,获取方法请参照Twikoo文档 lang: "zh-CN", // 评论区语言 }); // 传入配置信息 }; document.body.appendChild(script); } document.addEventListener("loadComment", loadTwikoo, { once: true }); // 监听加载评论事件,但是我们只能监听一次,从而避免多次触发。</script>随后,在src/pages/posts/[...slug].astro中导入这个组件,我们即可看到一个标准的Twikoo评论区组件。(思路参考了这篇文章)
<!--16行左右,不要忘了引入组件-->import Twikoo from '@components/comment/Twikoo.astro'
<!--- 111行左右新增 --><div class="card-base p-6 mb-4"><Twikoo path={`/posts/${entry.slug}`} /></div>
<div class="flex flex-col md:flex-row justify-between mb-4 gap-4 overflow-hidden w-full"> <!--原有的代码,方便参照代码插入位置--></div>
Twikoo 主题魔改
在上一节中,我们成功给 Fuwari 主题接入了 Twikoo 评论系统,但 Twikoo 的默认主题与 Fuwari 主题显得并不协调,我们希望能够将其强调色与 Fuwari 统一。并且在黑暗模式下,文本颜色并不会随 Fuwari 变化,仍然显示为默认的黑色,导致难以辨认,这我们可以通过修改 twikoo 的样式来解决。

这里 Twikoo 的样式其实是其twikoo.all.min.js中所内嵌的样式,当然 Twikoo 也提供了不内嵌 css 的版本供用户使用,从而能够更深度的自定义 Twikoo。在Twikoo 文档中,对不同的 js 文件的功能进行了划分。

我们仍然选择带有内嵌 css 的版本,从而在 Twikoo 内嵌样式的基础上去覆盖 Twikoo 原有样式,当然,从头开始定义 Twikoo 的样式亦可。由于我们仍然选择了内嵌 css 的版本,对 twikoo 的引入部分无需更改。
在src/styles创建 css 文件,文件名任取,在这里的样式将会被自动加载,我们可以在浏览器的审查模式下,对指定元素进行选中,并根据各个元素的类名,对元素进行选中,并使用 CSS 对其样式进行修改。

在这里,我们使用SCSS语法与Tailwindcss来简化开发,完整的 CSS 文件可以在我的Github Gists中下载。将 CSS 应用到 Fuwari 中,我们即可得到一个适配 Fuwari 主题强调色的 Twikoo 评论界面(整体布局布局参考自「园子里的时光」博客)。当然,也可以在我的 CSS 文件中,对主题进行进一步的修改。

其余问题
单击按钮返回顶部
参见Twikoo-Issues-731,目前可以通过修改 Twikoo 源码,将<a>标签内href="#"去除,再对 Twikoo 重新编译,并替换 Twikoo 导入。(待寻找更好的方法)
为评论区添加小标题
将Twikoo.astro中的<div id="comment"></div>使用WidgetLayout包围即可
I18nKey.comments这一项对应的i18n已在fuwari中包含,无需额外添加
---import WidgetLayout from "@components/widget/WidgetLayout.astro";// ...其他的导入---
<WidgetLayout name={i18n(I18nKey.comments)} id="comments"> <div id="comment"></div></WidgetLayout>
twikoo.css具有时效性,可能会随着fuwari或twikoo的改动失效,如需要自定义设置,可以尝试自行更改,此样式文件可作参考。fuwari,由于更改了代码块的实现,实际效果可能与本站不同。如需复制按钮可能需要开启Twikoo自身的复制功能。(更好的实现方案有待研究)你好,我发现您的Twikoo.astro实现在新的Fuwari版本中有bug
这里用了 { once: true },意味着只会响应 第一次 loadComment 事件,后续 Swup 页面切换时再 dispatchEvent(“loadComment”) 就不会触发了,所以评论区只会在首次打开时出现,之后就没了。
所以说我通过询问GPT做了debug
https://imgbed.ztab.dpdns.org/file/1755654917074_Twikoo.astro
这个实现我实测没有问题,也请问大佬有没有可能是我自己的环境问题还是说新版本Fuwari改了实现呢
也恳请大佬帮忙看看我写的这个版本有没有问题
initCommentComponent()方法在function init()和window.swup.hooks.on("content:replace")中均被正确调用。once的原因。你可以在初始化代码中添加日志输出来验证这一点。我这样的全局事件监听方式确实欠妥,可以考虑更换更好的实现。once,或尝试更换其他更好的实现方法。好的,以及是否和我的操作步骤有关系?我是从未修改网站刷新到修改网站的,但我觉得也不太可能。我有两个CDN,一个是VercelCDN,一个是CloudflareCDN,难道是这两个同时命中了缓存规则?还有可以挂友链吗https://bcsm.us.kg
这我就不太清楚了。友链已经添加了,欢迎
感觉还不错,就是看起来不熟挺麻烦的。
好看
感觉不错啊