mirror of
https://github.com/liubinfighter/csv-lite.git
synced 2026-07-22 05:43:52 +00:00
3.3 KiB
3.3 KiB
CSV Lite 插件右键菜单问题排查与重构全记录
背景
在开发 CSV Lite 插件的过程中,遇到了表格右键菜单(context menu)在 UI/UX 上表现异常、事件处理混乱、菜单关闭不及时等一系列问题。为提升用户体验和代码可维护性,我们对菜单功能进行了彻底重构。本文详细记录了整个排查、修复与重构的过程。
1. 问题现象
- 右键菜单弹出后,点击菜单项第一次不会消失,第二次才消失。
- 菜单项 hover 效果偶尔失效。
- 菜单关闭后高亮未能及时清除。
- 控制台报错
addClass/removeClass is not a function或tableEl.addEventListener is not a function。 - 工具栏等 UI 元素偶尔消失。
2. 初步排查
2.1 事件监听与 DOM 结构
- 检查菜单项点击事件,发现菜单关闭逻辑依赖于
addClass/removeClass,但项目中并未实现这两个方法。 - 事件监听器绑定和解绑时机混乱,可能导致多次绑定或未解绑。
2.2 代码实现问题
- 右键菜单相关代码分散,UI 与数据操作耦合严重。
- 菜单项点击后,
closeMenu()并未总是被及时调用。 - 绑定菜单的时机不对,
tableEl可能还未渲染。
3. 修复与重构过程
3.1 替换 addClass/removeClass
- 将所有
addClass/removeClass替换为标准的classList.add/classList.remove,保证样式切换生效。
3.2 菜单关闭逻辑梳理
- 确保菜单项点击后立即关闭菜单,并清除高亮。
- 保证 ESC/点击外部也能关闭菜单。
3.3 彻底重构菜单栏功能
- 新增
MenuManager类,专门负责菜单的创建、显示、关闭。 - 菜单项通过参数传递,点击后自动关闭并调用回调。
- 只在表格渲染后(即
refresh()里)绑定右键菜单,确保tableEl已经是<table>元素。 - UI/UX 逻辑与数据操作彻底解耦,接口兼容原有调用方式。
3.4 修正绑定时机
- 移除
onOpen里的菜单绑定,只在refresh()里绑定,避免tableEl未初始化时报错。
4. 最终方案
- 右键菜单功能完全由
MenuManager管理,UI 逻辑清晰、无副作用。 - 菜单项包括:行/列的插入、删除、交换,所有操作均通过回调传递。
- 菜单关闭时自动清除高亮,支持 ESC/点击外部关闭。
- 只在表格渲染后绑定菜单,避免 DOM 未就绪导致的报错。
- 工具栏、表格等 UI 元素全部恢复正常。
5. 经验总结
- UI 组件应与数据操作解耦,便于维护和扩展。
- 事件监听器的绑定和解绑时机必须严格把控,避免内存泄漏和多次绑定。
- DOM 操作要确保目标元素已渲染,否则易出现
xxx is not a function报错。 - 标准化样式操作,优先使用
classList,避免自定义扩展污染全局。 - 重构时优先考虑单一职责原则,如本次将菜单管理独立为
MenuManager。
6. 参考代码片段
// 绑定菜单的正确方式
this.headerContextMenuCleanup = setupHeaderContextMenu(
this.tableEl,
{
selectRow: (rowIndex) => this.highlightManager.selectRow(rowIndex),
// ... 其他回调 ...
}
);
本次重构极大提升了插件的健壮性和用户体验,也为后续功能扩展打下了坚实基础。