19

wangEditor输入中文后直接粘贴bug来了解compositionstart

 3 years ago
source link: https://www.daozhao.com/9934.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

昨天有人反馈邮件编辑过程中的一个报障,具体内容就是在编辑器中输入中文然后直接粘贴先前复制好的信息,然后出现了bug,比如之前复制了订单号“1234”,再输入“您的订单号”后直接粘贴,编辑器内显示的结果是“1234您的订单号”,这是不符合预期的,报障了给录屏信息,看的出其实是输入光标问题导致,点击编辑器内区域开始编辑时光标是落在最前方,也就是“您”字的前面,粘贴后实际上页面显示的光标是落在“号”字后面的,但是粘贴时确还是认为光标在“您”字前方,所以“1234”就落在了“您”的前面了,而不是大家预期的“号”后面。英文输入无此问题。 鉴于编辑器用的是wangEditor,我很自然的想到如果这个bug真的存在的,wangEditor多半也是有的,跑到官网看了下,并没有。邮件项目的web版也没有此bug,但是邮件项目其实是在壳里面的,公司老版的壳是QT,新版的是Electron版,目前新版还在灰度中,只有少部分人在使用,实测该问题在QT上存在,Electron版上没有。 中文输入法的问题很容易想到是不是要用 compositionstartcompositionendcompositionupdate 了,在此之前我们可以先看看wangEditor是记录当前光标的位置的。

javascript
// 绑定事件
_bindEvent: function _bindEvent() {
    // 实时保存选取
    this._saveRangeRealTime();

    // 按回车建时的特殊处理
    this._enterKeyHandle();
    ....
}

// 实时保存选取
_saveRangeRealTime: function _saveRangeRealTime() {
    var editor = this.editor;
    var $textElem = editor.$textElem;

    // 保存当前的选区
    function saveRange(e) {
      // 随时保存选区
      editor.selection.saveRange();
      // 更新按钮 ative 状态
      editor.menus.changeActive();
    }
    // 按键后保存
    $textElem.on('keyup', saveRange);
    $textElem.on('mousedown', function(e) {
      // mousedown 状态下,鼠标滑动到编辑区域外面,也需要保存选区
      $textElem.on('mouseleave', saveRange);
    });
    $textElem.on('mouseup', function(e) {
      saveRange();
      // 在编辑器区域之内完成点击,取消鼠标滑动到编辑区外面的事件
      $textElem.off('mouseleave', saveRange);
    });
},

可以看到在 keyup 的时候就实时保存选区了,简单测试了下,在QT版壳里面使用中文编辑时,虽然编辑器内光标如预期般更新,但是未曾触发 keyup 事件,英文输入是不存在此问题的。

现在是该 compositionstartcompositionendcompositionupdate 上场了。

在输入法开始输入中文时会触发 compositionstart ,输入结束时会触发 compositionend ,我需要简单记录下即可。 更完整的方案可以参考element-ui的input,里面还针对韩语进行了兼容。

handleCompositionStart() {
        this.isComposing = true;
},
handleCompositionUpdate(event) {
        const text = event.target.value;
        const lastCharacter = text[text.length - 1] || '';
        this.isComposing = !isKorean(lastCharacter);
},
handleCompositionEnd(event) {
        if (this.isComposing) {
          this.isComposing = false;
          this.handleInput(event);
        }
},

function isKorean(text) {
  const reg = /([(\uAC00-\uD7AF)|(\u3130-\u318F)])+/gi;
  return reg.test(text);
}

据此我们更新下wangEditor部分代码即可

_saveRangeRealTime: function _saveRangeRealTime() {
    var editor = this.editor;
    var $textElem = editor.$textElem;
    var isComposing = false;

    // 保存当前的选区
    function saveRange(e) {
        // 随时保存选区
        editor.selection.saveRange();
        // 更新按钮 ative 状态
        editor.menus.changeActive();
    }

    function isKorean(text) {
        const reg = /([(\uAC00-\uD7AF)|(\u3130-\u318F)])+/gi;
        return reg.test(text);
    }

    function handleCompositionStart() {
        isComposing = true;
    }

    function handleCompositionUpdate(event) {
        const text = event.target.value;
        const lastCharacter = text[text.length - 1] || '';
        isComposing = !isKorean(lastCharacter);
    }

    function handleCompositionEnd(event) {
        if (isComposing) {
            isComposing = false;
            saveRange();
        }
    }
    // 按键后保存
    $textElem.on('keyup', saveRange);
    $textElem.on('compositionstart', handleCompositionStart);
    $textElem.on('compositionupdate', handleCompositionUpdate);
    $textElem.on('compositionend', handleCompositionEnd);
    $textElem.on('mousedown', function(e) {
        // mousedown 状态下,鼠标滑动到编辑区域外面,也需要保存选区
        $textElem.on('mouseleave', saveRange);
    });
    $textElem.on('mouseup', function(e) {
        saveRange();
        // 在编辑器区域之内完成点击,取消鼠标滑动到编辑区外面的事件
        $textElem.off('mouseleave', saveRange);
    });
},

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK