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;}