本帖最后由 Zapic 于 2020-2-28 19:38 编辑
其实...
刚刚我在策划怎么发锭...
然后就发现了这个Bug了.
#1 问题重现
由于习惯问题,编辑帖子时会来回切换纯文本模式和正常模式.
然后来回几次之后,刚刚想At人来领锭,后来直接蹦出来5个@.
exm?
然后我怀疑是我的脚本问题,直接把脚本关掉了.
然并卵.
然后我怀疑是我的浏览器问题,换成了IE.
然并卵.
然后我怀疑是我键盘的问题,换了块键盘.
然并卵.
然后我怀疑是我家闹鬼了,找了位热心世予.
世予: 我早就踩过这个坑了.
然后我就来这里发帖了.
然后,这是演示图:
IE11 on Windows 7:
Chrome 80 on Windows 7:
然后...
(别然后了!你找死啊!)
咳咳.
然...呸.
那么欢迎测试.
#2 导致问题的原因
我拿着DevTools删了半天监听器都没删干净,还在查,欢迎一起为论坛做贡献(
哈!
查到了,不愧是我.
哈↑哈↑哈↑哈↑
咳咳.
先从点击切换编辑器的按钮查起,就先查到了switchEditor方法.
然后查看源代码,发现如下内容:- function switchEditor(mode) {
- //省略30行
- $(editorid + '_mode').value = mode;
- newEditor(mode, parsedtext);
- setEditorStyle();
- editwin.focus();
- setCaretAtEnd();
- }
复制代码
前几行都在控制顶栏的行为,与输入框没有关系,直接从下面查起:
然后先查newEditor方法:- function newEditor(mode, initialtext) {
- //省略40行
- setEditorEvents();
- initEditor();
- }
复制代码
前几行都在控制编辑框的显示行为和内容保存,直接看到setEditorEvents方法:- function setEditorEvents() {
- if (BROWSER.firefox || BROWSER.opera) {
- editdoc.addEventListener('mouseup', function(e) {
- mouseUp(e)
- }, true);
- editdoc.addEventListener('keyup', function(e) {
- keyUp(e)
- }, true);
- editwin.addEventListener('keydown', function(e) {
- keyDown(e)
- }, true);
- } else if (editdoc.attachEvent) {
- try {
- editdoc.attachEvent('onmouseup', mouseUp);
- editdoc.attachEvent('onkeyup', keyUp);
- editdoc.attachEvent('onkeydown', keyDown);
- } catch (e) {}
- }
- }
复制代码 再一路追查keyDown方法:- function keyDown(event) {
- ctlent(event);
- for (i in EXTRAFUNC['keydown']) {
- EXTRAEVENT = event;
- try {
- eval(EXTRAFUNC['keydown'][i] + '()');
- } catch (e) {}
- }
- }
复制代码
然后追查EXTRAFUNC['keydown']内含的元素,发现只有一个"extrafunc_atMenu"方法,我们越来越接近真相了:- function extrafunc_atMenu() { if (BROWSER.opera) {
- return;
- }
- if (wysiwyg && EXTRAEVENT.shiftKey && EXTRAEVENT.keyCode == 50 && postaction && (postaction == 'newthread' || postaction == 'reply' || postaction == 'edit')) {
- keyMenu('@', atMenu);
- ctlent_enable[13] = 0;
- doane(EXTRAEVENT);
- atkeypress = 1;
- }
- if ($('at_menu') && $('at_menu').style.display == '' && (EXTRAEVENT.keyCode == 38 || EXTRAEVENT.keyCode == 40 || EXTRAEVENT.keyCode == 13)) {
- doane(EXTRAEVENT);
- }
- }
复制代码
果然,这里是实现@弹出菜单的方法. |
然后追查到底了,问题也水落石出了.
在调用setEditorEvents方法时,没有移除旧的监听器,导致编辑器上有多个监听器,而且是来回切换一次就多一个,导致一次按键触发多次extrafunc_atMenu方法,进而导致@符号超级加倍.
那问题很好解决啊,调用setEditorEvents时,把编辑器上旧的监听器移除掉,再进行接下来的操作就可以了.
结果发现睿智Discuz添加监听器时用的是匿名函数,没法移除(
既然他们睿智操作那我们也可以睿智操作,让setEditorEvents方法只能使用一次,用过就自毁:
- var __setEditorEvents = setEditorEvents;
- setEditorEvents= function(){
- __setEditorEvents();
- setEditorEvents=function(){};
- }
复制代码
不愧是我(
#3 迫 害 宝 座
@gamerteam 出来修Bug啦!泥潭已经一个月没有更新啦!