需求说明:两个系统不同数据库数据交互时,由于数据库存储字节长度不同导致定义字节长度参差不齐,后端无法修改,所以重任落到了前端头上从源头上限制传给后端的字符长度,普通后端定义长度为 1 字符前端限制字符长度为 1 就行,现在需要改成 数字英文占一个字符,中文占两个字符其他占四个字符。
首先在 main.js 写入
// 输入框千分位符处理
var desc = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value')
Object.defineProperty(HTMLInputElement.prototype, 'value', {
...desc,
set(v) {
if (this.getAttribute('data-maxCharShow') === 'true') {
let maxCharlength = Number(this.getAttribute('data-maxCharlength')) || 0
let span = this.parentNode.parentNode.nextElementSibling
let b = 0 // 输入的字符数
for (var i = 0, length = v.length; i < length; i++) {
var c = v.charAt(i);
if (/^[`!¥……()——\{}|《》?:“”【】、;‘',。、\s+]$/.test(c)) {
b += 4;
} else if (/^[\u4e00-\u9fa5]$/.test(c)) {
b += 2;
} else {
b++;
}
if (b > maxCharlength) {
if (/^[`!¥……()——\{}|《》?:“”【】、;‘',。、\s+]$/.test(c)) {
b-=4
} else if (/^[\u4e00-\u9fa5]$/.test(c)){
b -= 2;
} else {
b--;
}
break
}
}
span.innerText = b + ' / ' + maxCharlength
}
desc.set.call(this, v)
}
})
输入框加上特殊属性 data-maxCharShow="true" data-maxCharlength="10"
data-maxCharShow: 是否触发字符长度重新计算
data-maxCharlength:可输入字符最大长度
<el-input v-model="ruleForm.name" placeholder="请填写企业名称" v-maxlength data-maxCharShow="true" data-maxCharlength="10" maxlength="10" class="inputDesc"></el-input>
添加自定义指令,监听是否获取焦点转换字符长度,由于@change和@input都无法再输入框被赋值时触发所以需要 Object.getOwnPropertyDescriptor()和Object.defineProperty() 方法
// 根据字节判断长度
app.directive('maxlength', {
beforeMount(el, binding, vnode) {
let input = el.children[0].children[0]
input.addEventListener('focus', function(ev) {
// 修改是否转换属性为false
input.setAttribute('data-maxCharShow', 'false')
})
// 非直接输入开始
input.addEventListener('compositionstart', function(ev) {
input.setAttribute('data-open', 'false')
})
// 非直接输入结束
input.addEventListener('compositionend', function(ev) {
input.setAttribute('data-open', 'true')
var target = input;
let e = target.value
var maxCharlength = target.getAttribute("data-maxCharlength")
var num = Number(target.getAttribute("data-maxCharlength"))
let b = 0 // 输入的字符数
for (var i = 0, length = e.length; i < length; i++) {
var c = e.charAt(i);
if (/^[`!¥……()——\{}|《》?:“”【】、;‘',。、\s+]$/.test(c)) {
b += 4;
num -= 2
} else {
if (/^[\u4e00-\u9fa5]$/.test(c)) {
b += 2;
num-=1
} else {
b++;
}
}
if (b > maxCharlength) {
if (/^[`!¥……()——\{}|《》?:“”【】、;‘',。、\s+]$/.test(c)) {
b -= 4;
num+=2
} else {
if (/^[\u4e00-\u9fa5]$/.test(c)) {
b -= 2;
num+=1
} else {
b--;
}
}
break
}
}
target.value=e
target.setAttribute("maxlength", num)
if (target.tagName.toLowerCase() == 'input') {
let span = target.parentNode.parentNode.nextElementSibling
span.innerText = b + ' / ' + maxCharlength
}
})
input.addEventListener('input', function(ev) {
if (input.getAttribute('data-open')==='false') return
var target = input;
let e = target.value
// 获取总长度判断回显
var maxCharlength = target.getAttribute("data-maxCharlength")
// 获取总长度 改变 maxlength 属性 用原生控制不可输入
var num = Number(target.getAttribute("data-maxCharlength"))
let b = 0 // 输入的字符数
for (var i = 0, length = e.length; i < length; i++) {
var c = e.charAt(i);
if (/^[`!¥……()——\{}|《》?:“”【】、;‘',。、\s+]$/.test(c)) {
b += 4;
num-=2
} else {
if (/^[\u4e00-\u9fa5]$/.test(c)) {
b += 2;
num-=1
} else {
b++;
}
}
if (b > maxCharlength) {
if (/^[`!¥……()——\{}|《》?:“”【】、;‘',。、\s+]$/.test(c)) {
b -= 4;
num+=2
} else {
if (/^[\u4e00-\u9fa5]$/.test(c)) {
b -= 2;
num+=1
} else {
b--;
}
}
break
}
}
target.value=e
target.setAttribute("maxlength", num)
if (target.tagName.toLowerCase() == 'input') {
let span = target.parentNode.parentNode.nextElementSibling
span.innerText = b + ' / ' + maxCharlength
}
})
input.addEventListener('blur', function(ev) {
// 修改是否转换属性为false
input.setAttribute('data-maxCharShow', 'true')
})
}
})
最后代码如下
<el-input v-model="ruleForm.name" placeholder="请填写企业名称" v-maxlength data-maxCharShow="true" data-maxCharlength="10" maxlength="10" class="inputDesc"></el-input>
<span class="input-count">0 / 10</span>
span 里面数字会跟着输入的字符也一起变化。