vue自定义指令之输入框限制字数

  目录

input输入框限制字数的指令制作

vue自定义指令之输入框限制字数

vue自定义指令没啥说的,说明见官网,具体代码见下面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Vue.directive('inputvalidatecounter', {
inserted: function (el, binding) {
var nSpan = document.createElement('span'),
nInput = el.querySelector('input'),
count = +binding.expression || 50;
el.appendChild(nSpan);
nSpan.innerHTML = '还可以填写'+count+'字';
nInput.addEventListener('input', function(ev) {
var num = count - this.value.length;
if(num<=0) {
setTimeout(() => {
var substr = this.value.substring(0,count-1);
this.value = substr;
}, 10);
}
nSpan.innerHTML = '还可以填写'+(num<0?0:num)+'字';
}, false);
}
});

需要注意的地方:

  • 这个指令只适用于iview的Input组件,看里边操作dom元素就可以看出来,想改成其它的也是简单。
  • 在更改input的value的时候,最开始改不过来,后来我做了下延迟才解决这个问题,我想应该是在直接给input的value赋值后由于vue还在做监控,所以又给改回去了,所以来个延迟,在它监控触发结束后再改正。

2019年3月4日更改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Vue.directive('inputvalidatecounter', {
inserted: function (el, binding, vnode) {
var nSpan = document.createElement('span'),
nInput = el.querySelector('input') || el.querySelector('textarea'),
count = +binding.expression || 50;
el.appendChild(nSpan);
nSpan.innerHTML = '还可以填写'+count+'字';
nInput.addEventListener('input', function(ev) {
var num = count - this.value.length;
if(num<=0) {
setTimeout(() => {
var substr = this.value.substring(0,count);
this.value = substr;
// 新添加开始
var keyArr = vnode.data.model.expression.split('.');
var evalStr = 'vnode.context._data';
keyArr.forEach((item, index)=> {
evalStr += '["'+item+'"]';
});
eval(evalStr+'="'+this.value+'"')
// 新添加结束
}, 10);
}
nSpan.innerHTML = '还可以填写'+(num<0?0:num)+'字';
}, false);
}
});

新添加的内容只有几行,其实是为了修改第一版的bug,当在input里输入内容的时候,超过一定字数后,进入延迟函数,这里把input的value值更改了,但是并没有更改这个指令所在组件里v-model的值,所以,这里需要修正。

1
2
3
4
5
6
7
8
9
10
11
// vnode是这个指令所在的组建的虚拟dom
// vnode.data.model.expression 这就可以直接找到v-model里的变量名
var keyArr = vnode.data.model.expression.split('.');
// vnode知道了,vnode.context很显然就是组件所在的父级组件,可以通过 _data 这个数据去改变v-model里变量的值。
var evalStr = 'vnode.context._data';
keyArr.forEach((item, index)=> {
evalStr += '["'+item+'"]';
});
// 经过上边的循环是因为这种情况, v-model="formitem.name",像这种的值,而不是v-model="name"这种。
// 最后需要eval来执行这些字符串组成的代码。
eval(evalStr+'="'+this.value+'"')