Vue.component('input-len-control', {
template: `
<div class="input-control-wrapper">
<input type="text" v-model="input" @input="inputControl($event.target.value)" :placeholder="placeholder">
<span class="control">{{curLen}}/{{maxLen}}</span>
</div>
`,
data() {
return {
curLen: 0, // 以后 input 值的长度
input: ''
}
},
// 父子组件双向绑定
model: {
prop: 'inputValue',
event: 'change'
},
props: {
maxLen: {
type: Number,
default: 16
},
placeholder: String,
inputValue: {
type: String,
default: ''
}
},
watch: {
// 初始化时携带默认值
inputValue: {handler(val) {
const {
returnStr,
len
} = getTagLen(val, this.maxLen)
this.curLen = len
this.input = returnStr
},
immediate: true
}
},
mounted() {},
methods: {inputControl(val) {
const {
returnStr,
len
} = getTagLen(val)
this.curLen = len
this.input = returnStr
this.$emit('change', returnStr)
}
}
})
function getTagLen(str, maxLen) {let reg = /^[\u4e00-\u9fa5]{0,}$/;
let len = 0;
let returnStr = "";
if (str === "") {
return {
returnStr,
len
}
}
str = str.split('');
for (let i = 0; i < str.length; i++) {if (reg.test(str[i])) {if (len >= maxLen -1) break;
len += 2;
} else {len++;}
returnStr += str[i];
if (len >= maxLen) break;
}
return {
returnStr,
len
}
}
根本款式
.input-control-wrapper {
position: relative;
height: 32px;
}
.input-control-wrapper input[type="text"] {
box-sizing: border-box;
width: 100%;
height: 32px;
border: 1px solid #ccc;
line-height: 32px;
padding-left: 6px;
padding-right: 35px;
color: #333;
}
.input-control-wrapper .control {
position: absolute;
width: 35px;
line-height: 32px;
font-size: 12px;
color: #999999;
right: 0;
top: 0;
text-align: center;
}