经常有需求,在限制文本框输入长度的时候,区分中英文,如:中文(全角符号类似)占两个字节,英文则占一个,最近审查代码,发现项目上存在类似需求,组内同学实现了网上经常提到的方案,输入后替换,由于监听的是input事件,导致任何越界输入都会出现闪烁的情况,不同于原生效果。
回忆到以前曾经用keydown结合其他事件实现了一版,晚上没事,就尝试重新实现了一下,由于目前项目不考虑非webkit内核浏览器,只在chrome下简单测试了下,有兼容性问题欢迎评论告知
const keyCode = [37, 38, 39, 40, 91, 8, 46, 34, 12, 20] const specialKeyCode = [65, 67, 88] function getLength(value) { return value.replace(/[^ -~]/g, '00').length } function slice(value, maxlength) { if (maxlength && maxlength > -1) { while (getLength(value) > maxlength) { value = value.slice(0, value.length - 1) } } return value } function checkKeydown(e) { const code = e.keyCode return !((e.metaKey || e.ctrlKey) && specialKeyCode.includes(code)) && !keyCode.includes(code) } function limit(target, targetValue) { const value = targetValue || target.value const maxLength = target.maxLength let newValue = value if (maxLength > -1 && getLength(newValue) >= maxLength) { newValue = slice(newValue, maxLength) } if (newValue !== value) { target.value = newValue target.focus() } } function compositionEnd(e) { const target = e.target const maxLength = target.maxLength if (maxLength > -1 && getLength(target.value) > maxLength) { limit(target) } } function limitMaxLength(input) { input.addEventListener('keydown', e => { const target = e.target const maxLength = target.maxLength const value = target.value if (maxLength > -1 && getLength(value) >= maxLength && checkKeydown(e)) { e.preventDefault() e.stopPropagation() } }) input.addEventListener('input', e => { if (!e.isComposing) { compositionEnd(e) } }) input.addEventListener('compositionend', compositionEnd) input.addEventListener('paste', e => { e.preventDefault() e.stopPropagation() const target = e.target const insert = e.clipboardData.getData('text/plain') const selectionStart = target.selectionStart const value = target.value limit(target, value.slice(0, selectionStart) + insert + value.slice(selectionStart)) }) } limitMaxLength(document.getElementById('input'))上一篇: node gRPC *.proto 生成 js/ts 下一篇: 基于Array的JavaScript表达式执行函数实现