内容提要
Waline评论系统存在一个bug,即回复评论后,评论内容不会自动清空。经过分析发现,评论内容保存在localStorage中。通过查找代码,发现问题出在watch函数中,当提交评论后,editor.value被清空,但watch函数触发时,取到的是旧值。问题可能是由于submitComment是异步函数,导致editor.value=''没有及时更新。进一步调试发现,watch函数被onMounted触发,当顶部的CommentBox.vue组件重新渲染时,watch函数会被触发,此时取到的是旧值。问题可能是useEditor()函数内部有异步操作,导致localStorage没有立即更新。解决方法是使用localStorage.setItem('WALINE_COMMENT_BOX_EDITOR', '')或await nextTick()等待DOM更新完成。
延伸解读
问题根源:异步时序与组件生命周期
该 bug 的核心在于异步操作与 Vue 组件生命周期的交互。submitComment 是异步函数,执行 editor.value = '' 后,localStorage 的更新可能未立即完成。同时,回复评论时,CommentCard 内的 CommentBox 销毁,顶部的 CommentBox 重新渲染,触发 onMounted 中的 watch,此时从 localStorage 读取的仍是旧值,导致输入框内容未清空。
调试手段:利用 watch 的 onTrack 与 onTrigger
作者通过为 watch 添加 onTrack 和 onTrigger 调试钩子,追踪依赖变化。onTrigger 在 editor.value 被修改时触发,显示新值为空字符串;onTrack 在依赖被追踪时触发,但取到的是旧值。这证实了 watch 回调执行时,editor.value 尚未更新,帮助定位了异步时序问题。
解决方案:直接操作 localStorage 或等待 DOM 更新
文章提出两种修复方式:一是直接使用 localStorage.setItem('WALINE_COMMENT_BOX_EDITOR', '') 绕过响应式系统的异步更新;二是使用 await nextTick() 等待 DOM 更新完成后再执行后续逻辑。这两种方法都能确保在组件重新渲染前,localStorage 中的评论内容已被清空,从而避免旧值被读取。
Q&A
Waline评论系统的bug是什么?
Waline评论系统的bug是回复评论后,评论内容不会自动清空,仍然保留在输入框中。
这个bug的根本原因是什么?
根本原因在于watch函数触发时取到的是editor.value的旧值,导致评论内容未能及时清空。
如何解决这个bug?
可以通过使用localStorage.setItem('WALINE_COMMENT_BOX_EDITOR', '')或await nextTick()来解决这个bug。
为什么watch函数会取到旧值?
因为submitComment是异步函数,editor.value=''没有及时更新,导致watch在组件重新渲染时取到旧值。
localStorage在这个bug中起什么作用?
localStorage用于保存评论内容,即使刷新浏览器也不会清空,导致bug的出现。
如何调试这个bug?
可以通过在watch中添加debug函数,观察editor.value的变化,来调试这个bug。