vue指令处理输入框时微软输入法无法输入问题

1.环境

语言:vue

输入法:微软输入法

2.场景举例

采用指令方式实现一个只允许输入中午的输入框。但是在使用微软输入法时,由于输入汉字的时候在未输入完成的时候输入法已经把拼音输入到input中,这样就会触发我们指令逻辑导致拼音被清除,所以导致无法输入。

3.解决思路

使用输入框事件compositionstart和compositionend监听是否开启新的输入或者结束本次输入,如果开启新的输入就不允许更新,如果结束输入就允许更新

事件说明:

compositionstart

文本合成系统如 input method editor(即输入法编辑器)开始新的输入合成时会触发 compositionstart 事件。

例如,当用户使用拼音输入法开始输入汉字时,这个事件就会被触发。

compositionend

当文本段落的组成完成或取消时,compositionend 事件将被触发 (具有特殊字符的触发,需要一系列键和其他输入,如语音识别或移动中的字词建议)。

4.案例

Vue.directive('limitInput', ()=>{

  /* 兼容性检测

    chrome:oncompositionstart--->oninput--->oncompositionend

    firefox: oncompositionstart--->oncompositionend--->oninput */

  /* 限制输入中文+空格/英文+空格/数字+空格/保留 binding.value 位小数 */

  bind(el, binding) {

    const arg = binding.arg

    // 限制规则

    const restrictRule = {

      zh: /[^\s\u4E00-\u9FA5\s]/g, // 中文

      en: /[^a-zA-Z\s]/g, // 英文

      number: /[^0-9]/g, // 纯数字

      float: (val) => {

        // 保留 v-limitInput:float="n" n位小数数字

        val =

          val.indexOf('.') > -1

            ? val.slice(0, val.indexOf('.') + binding.value + 1)

            : val

        return val.replace(/[^0-9\.]/g, '')

      }

    }

    const multiValitor = ['float'] // 多重限制类型

    const restrict = restrictRule[binding.arg]

    let inputLock = false // 输入锁 使用输入法时关闭限制 结束输入法输入时触发限制

    const doRule = (e) => {

      // 判断是否多重校验形式

      if (multiValitor.indexOf(arg) === -1) {

        e.target.value = e.target.value.replace(restrict, '')

      } else {

        e.target.value = restrictRule[arg](e.target.value)

      }

      // 手动更新绑定值

      e.target.dispatchEvent(new Event('input'))

    }

    const target =

      el instanceof HTMLInputElement ? el : el.querySelector('input')

    target.addEventListener('input', (event) => {

      /*

        若不是手动输入(inputType === 'insertText'),是更新时触发此事件则不再执行校验

        防 dispatchEvent 无限触发限制校验

      */

      if (!inputLock && event.inputType === 'insertText') {

        doRule(event)

        event.returnValue = false

      }

      event.returnValue = false

    })

    /* 使用输入法开始触发 */

    target.addEventListener('compositionstart', (event) => {

      inputLock = true

    })

    /* 结束输入法使用触发 */

    target.addEventListener('compositionend', (event) => {

      inputLock = false

      doRule(event)

    })

  }

}

)


案例基于:https://juejin.cn/post/7081088003531079687?searchId=20240506174617A2F6C79CB31095069E68

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容