省流版:看 解决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) => {
loginForm.imgCode = $event.target.value.replace(/[^0-9a-zA-Z]/g, "");
};
问题3
本以为 1 && 2 组合拳下去,事情会解决,但发现使用拼音输入法,在输入法还没合成中文时会直接触发 input
事件,导致过滤后与预期不符
解决3
通过一番搜索,知道在输入合成时会有 compositionstart
事件,结束时也会有 compositionend
事件,需要在输入合成结束之后再对输入进行过滤
<van-field
maxlength="4"
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);
};