找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 55|回复: 0

[维护日志] [2026-08-27] [修复] [编辑器粘贴重复] - 所见即所得编辑器切换模式后粘贴内容重复问题修复

[复制链接]
  • 打卡等级:本地老炮

9337

威望

7448

金钱

1万

贡献

管理员

自由的灵魂

积分
107434
主题
5630
回帖
26661
注册时间
2003-4-10
最后登录
2026-10-2
发表于 2026-8-27 22:08:49 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
当前版本:Discuz X3.5

1、问题缘起

论坛发帖编辑器存在一个问题:在所见即所得(WYSIWYG)模式下,每次从纯文本模式切换回可视化模式后,粘贴操作都会将剪贴板内容重复插入多次。

具体现象:

场景粘贴结果说明
初次进入可视化编辑器粘贴出 1 份内容(A)正常
切换到纯文本模式,再切回可视化模式粘贴出 2 份内容(AA)异常
再切换到纯文本模式,再切回可视化模式粘贴出 3 份内容(AAA)异常


根本原因:setEditorEvents() 函数在每次切换到可视化模式时都会被调用,其中包含的 paste 事件监听器使用匿名函数,导致每次调用都会新增一个监听器,而旧的监听器没有被移除。多次切换后,同一个 paste 事件触发了多个监听器,导致粘贴内容被重复插入。

相关子问题:
  • 纯文本模式下粘贴正常,不受影响
  • 问题仅在切换到可视化模式后出现
  • 切换次数与重复次数成正比

2、解决方案

(1)简要技术分析:

使用一个全局标志变量 window._pasteBound 记录 paste 监听器是否已被绑定,确保在整个页面生命周期中只绑定一次,避免重复添加。

(2)修改文件列表:

操作文件路径
修改/static/js/editor.js


(3)关键代码段:

修改一:在 setEditorEvents 函数开头添加标志变量(约第 230 行)

  1. function setEditorEvents() {
  2.     // ----- 防止 paste 监听器重复绑定 -----
  3.     if (typeof window._pasteBound === 'undefined') {
  4.         window._pasteBound = false;
  5.     }
  6.     // ------------------------------------------
  7.     // ... 后续代码
  8. }
复制代码


修改二:将原有匿名 paste 监听器包裹在条件判断中(约第 238 行)

  1.         // ----- paste 事件监听(仅绑定一次) -----
  2.         if (!window._pasteBound) {
  3.             editdoc.addEventListener('paste', function(e) {
  4.                 var clipboardData = e.clipboardData || window.clipboardData;
  5.                 if (!clipboardData) return;
  6.                 var text = clipboardData.getData('text/plain');
  7.                 if (text) {
  8.                     e.preventDefault();
  9.                     if (wysiwyg) {
  10.                         editdoc.execCommand('insertText', false, text);
  11.                     } else {
  12.                         var start = editdoc.selectionStart;
  13.                         var end = editdoc.selectionEnd;
  14.                         var value = editdoc.value;
  15.                         editdoc.value = value.substring(0, start) + text + value.substring(end);
  16.                         editdoc.selectionStart = editdoc.selectionEnd = start + text.length;
  17.                     }
  18.                 }
  19.             }, true);
  20.             window._pasteBound = true;
  21.         }
  22.         // -------------------------------------------------
复制代码


3、最终实现效果

测试场景修复前修复后
初次进入可视化编辑器后粘贴1 份内容1 份内容
切纯文本→切回可视化后粘贴2 份内容1 份内容
再切纯文本→再切回可视化后粘贴3 份内容1 份内容
多次切换后粘贴重复次数递增始终 1 份内容


所有切换模式下粘贴行为保持一致,内容不再重复。

4、重要技术沉淀

需更新到固化摘要:

  1. 二十四、编辑器 paste 事件监听重复绑定问题(2026-08-27)

  2. 问题:切换编辑器模式后粘贴内容重复
  3. 原因:setEditorEvents() 每次调用都会添加新的匿名 paste 监听器
  4. 解决:使用全局标志 window._pasteBound 控制监听器只绑定一次
  5. 涉及文件:static/js/editor.js
  6. 排查方法:切换模式次数与粘贴重复次数成正比,即可判断为监听器重复绑定
复制代码


踩坑点:

踩坑正确做法
用 removeEventListener 移除匿名函数匿名函数无法被移除,应使用命名函数或标志控制
在 switchEditor 中清空编辑器内容会导致用户正在编辑的内容丢失,不可取
每次切换都重新绑定监听器用标志控制只绑定一次,或在初始化时统一绑定


5、进一步优化可能性

  • 将 paste 监听器从 setEditorEvents 中分离:在编辑器初始化时统一绑定,避免与模式切换逻辑耦合
  • 使用命名函数替代标志控制:用 handlePaste 命名函数配合 removeEventListener 实现更精确的移除
  • 检查其他事件的重复绑定:mouseup、keyup 等事件是否存在类似问题


不懂就搜!点此搜点拨论坛。如果本坛没有,请尝试点此问AI,或跟帖提问。
发帖前注意看置顶帖。
不定期借助AI对点拨论坛陈年老帖进行挖坟回复,打扰勿怪!
有问题请直接提问,欢迎注册本论坛!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|点拨论坛 |网站地图

GMT+8, 2026-10-2 04:59 , Processed in 0.120750 second(s), 6 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表