Vue3 项目在 H5 + ios 环境中,input 输入框在输入中文未选中汉字时会触发 chang 事件,导致输入内容与预期不符

省流版:看 解决3

环境

vue3 + vant + H5

需求

input 输入框为验证码(隐含需求:用户接收到验证码时,需要复制验证码后可以点击输入法的联想词直接输入验证码,且需要仅能输入英文及数字)

问题与解决

问题1

  • iOS 自带的输入法输入验证码的时候会重复输入两次,比如收到验证码是 qw12,点击输入后会变成 qw12qw12

解决1

  • 使用 maxlength="4" 限制

问题2

  • 需要过滤非英文及数字

解决2

  • @input 时对输入进行过滤
<van-field
  maxlength="4"
  v-model="imgCode"
  @input="onInputCode"
  placeholder="请输入图形验证码"
  autocomplete="off"
/>
const imgCode = ref(null) // 验证码

const onInputCode = ($event) => {
  imgCode.value = $event.target.value.replace(/[^0-9a-zA-Z]/g, "");
};

问题3

本以为 1 && 2 组合拳下去,事情会解决,但发现使用拼音输入法,在输入法还没合成中文时会直接触发 input 事件,导致过滤后与预期不符

解决3

通过一番搜索,知道在输入合成时会有 compositionstart 事件,结束时也会有 compositionend 事件,需要在输入合成结束之后再对输入进行过滤

<van-field
  v-model="imgCode"
  @compositionstart="onCompositionStart"
  @compositionend="onCompositionEnd"
  @input="onInputCode"
  @change="onChangeCode"
  placeholder="请输入图形验证码"
  autocomplete="off"
/>
const imgCode = ref(null) // 验证码
const codeFlag = ref(false) // 输入合成时,延迟触发过滤

const onCompositionStart = () => {
  codeFlag.value = false
}

const onCompositionEnd = () => {
  codeFlag.value = true
}

const onInputCode = ($event) => {
  setTimeout(() => {
    if (!codeFlag.value) {
      return
    }
    imgCode.value = filterCode($event.target.value)
  }, 100)
};


const onChangeCode = ($event) => {
  if (codeFlag.value) {
    return
  }
  imgCode.value = filterCode($event.target.value)
}

// 对验证码输入进行过滤,限制为仅输入数字或字母,且长度为 4 位
const filterCode = (value) => {
  return value.replace(/[^0-9a-zA-Z]/g, "").slice(0, 4);
};

参考文档

posted @ 2022-10-08 14:34  to人间值得  阅读(965)  评论(0)    收藏  举报