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