Files
biji/memory-bank/activeContext.md
ikmkj 337645f27b fix(note-editor): 优化自动保存机制,解决切换笔记时的保存问题
- 修复了在切换笔记时意外触发自动保存的问题- 引入标志位区分用户输入和程序加载内容
-优化了自动保存的防抖逻辑,提高用户体验
- 删除了不必要的组件代码,精简结构
2025-08-14 07:49:40 +08:00

3.1 KiB
Raw Blame History

Bug 分析与修复报告:优化笔记编辑器自动保存机制

日期: 2025-08-13

作者: 你的智能小助手


1. 问题描述

在笔记应用中,自动保存功能存在一个体验问题:即使用户正在积极地编辑文本(持续输入),计时器也不会被正确地重置或停止。这导致了在用户输入间隙,即使是非常短暂的停顿,也会触发不必要的、频繁的保存操作。

理想的行为是:只有当用户停止输入一段时间后,自动保存才应该被触发。

相关文件: biji-qianduan/src/components/home/NoteEditor.vue

2. 分析与诊断过程

2.1. 初步代码审查

我首先审查了 NoteEditor.vue 的源代码,重点关注以下几个方面:

  • Vditor 编辑器集成: 代码通过 new Vditor() 正确初始化了编辑器。
  • 事件监听: 使用了 Vditor 的 input 事件回调来侦测内容变化。
  • 防抖Debounce逻辑: 在 input 回调中,存在一个看似正确的防抖实现:
    • 使用 let debounceTimer = null; 在组件作用域内声明了一个计时器变量。
    • 每次 input 事件触发时,都会先执行 clearTimeout(debounceTimer);
    • 然后通过 debounceTimer = setTimeout(...) 设置一个新的 2 秒延迟的计时器来执行保存操作 handleSave

从表面上看,这段代码逻辑是健全的,它确实实现了防抖的核心思想。

2.2. 深入诊断:发现真正原因

既然代码逻辑本身没有问题,为什么还会出现用户描述的现象呢?我提出了一个新的假设:问题并非出在用户输入时,而是出在切换笔记时。

  1. watch 监听器: 组件中使用 watch 来监听 props.editData 的变化。当用户从笔记列表选择一篇新笔记时,这个 prop 会更新。
  2. setValue 的副作用: watch 回调函数会调用 vditor.value.setValue(newData.content || '') 来将新笔记的内容加载到编辑器中。
  3. 意外的 input 事件: 关键在于Vditor 的 setValue 方法在设置内容后,会自动触发一次 input 事件
  4. 问题触发流程:
    • 用户点击一篇新笔记。
    • watch 监听到 props.editData 变化。
    • vditor.value.setValue() 被调用,加载新内容。
    • setValue() 触发了 input 事件。
    • input 事件的回调被执行,启动了一个为期 2 秒的自动保存计时器。
    • 即使用户立刻开始在这篇新笔记上输入(这会正确地重置计时器),那个由 setValue 启动的初始计时器依然可能在 2 秒后触发一次保存。

因此,根本原因是程序化地设置编辑器内容(setValue)意外地触发了为用户手动输入设计的自动保存逻辑。

3. 修复方案

为了解决这个问题,我们需要区分用户手动输入程序加载内容这两种情况。只有前者才应该触发自动保存。

我采用了一个**标志位flag**的方案来解决此问题:

  1. 引入标志位: 在 script setup 中增加一个 ref