vue自定义指令
vue的自定义指令有很多不错的小功能
-
仅能输入数字
-
元素外部点击收起
-
防止重复提交
-
输入字符长度限制
-
渲染html
1.仅能输入数字 numberOnly常用于输入金额或分数场合,不能输入负数,最多可以输入两位小数
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
Vue.directive('numberOnly', {
bind(el, binding, vnode) {
let input = vnode.elm;
input.addEventListener('compositionstart', () => {
vnode.inputLocking = true
})
input.addEventListener('compositionend', () => {
vnode.inputLocking = false
input.dispatchEvent(new Event('input'))
})
input.addEventListener('input', () => {
if(vnode.inputLocking) {
return;
}
let oldValue = input.value;
let newValue = input.value;
newValue = newValue.replace(/[^\d.]/g, '');
newValue = newValue.replace(/^\./g, '');
newValue = newValue.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.');
newValue = newValue.replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3')
if(newValue) {
let arr = newValue.split('.')
newValue = Number(arr[0]) + (arr[1] === undefined ? '' : '.' + arr[1]) // 去掉开头多余的0
}
// 判断是否需要更新,避免进入死循环
if(newValue !== oldValue) {
input.value = newValue
input.dispatchEvent(new Event('input')) // 通知v-model更新
}
})
// input 事件无法处理小数点后面全是零的情况 因为无法确定用户输入的0是否真的应该清除,如3.02。放在blur中去处理
input.addEventListener('blur', () => {
let oldValue = input.value;
let newValue = input.value;
if(newValue) {
newValue = Number(newValue).toString()
}
// 判断是否需要更新,避免进入死循环
if(newValue !== oldValue) {
input.value = newValue
input.dispatchEvent(new Event('input')) // 通知v-model更新
}
})
}
})
|
2.元素外部点击收起 clickOutSide带参数使用,参数为点击外部执行的方法,示例v-clickout-side=“function(){}” 表示点击外部触发的事件常见的应用场景是,点击div弹框外隐藏弹框。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
Vue.directive('clickOutSide', {
bind(el, binding, vnode) {
function documentHandler(e) {
// 这里判断点击的元素是否是本身,是本身,则返回
if (el.contains(e.target)) {
return false;
}
// 判断指令中是否绑定了函数
if (binding.expression) {
// 如果绑定了函数 则调用那个函数,此处binding.value就是handleClose方法
binding.value(e);
}
}
// 给当前元素绑定个私有变量,方便在unbind中可以解除事件监听
el.__vueClickOutside__ = documentHandler;
document.addEventListener('click', documentHandler);
},
update() {},
unbind(el, binding) { // 解除事件监听
document.removeEventListener('click', el.__vueClickOutside__);
delete el.__vueClickOutside__;
}
})
|
3.防止重复提交 preventDoubleClick发起后端请求时使用,防止重复点击。对于耗时较长的请求使用。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
Vue.directive('preventDoubleClick', {
inserted (el, binding) {
el.addEventListener('click', () => {
if (!el.disabled) {
el.disabled = true
setTimeout(() => {
el.disabled = false
}, binding.value '' 3000)
}
})
}
})
|
4.输入字符长度限制 maxlength输入框使用,用于限制输入字数限制,仅限制字数,如果需要更多复杂功能,可以使用el-input
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
28
29
|
Vue.directive('maxlength', {
bind(el, binding, vnode) {
let input = vnode.elm;
let max = binding.value;
input.addEventListener('compositionstart', () => {
vnode.inputLocking = true
})
input.addEventListener('compositionend', () => {
vnode.inputLocking = false
input.dispatchEvent(new Event('input'))
})
input.addEventListener('input', () => {
if(vnode.inputLocking) {
return;
}
let oldValue = input.value;
let newValue = input.value;
if(newValue.length > length) {
newValue = newValue.substring(0,max);
}
// 判断是否需要更新,避免进入死循环
if(newValue !== oldValue) {
input.value = newValue
input.dispatchEvent(new Event('input')) // 通知v-model更新
}
})
}
})
|
5.渲染html类似于vue自带的v-html指令,v-html使用innerHTML在当前元素下插入html内容,会保留当前dom元素的标签。这个指令使用outerHTML,不在保留原有元素的标签,能够更灵活的应用。详见链接
1
2
3
4
5
6
7
8
|
Vue.directive('oHtml', {
inserted: (el, dir) => {
if (dir.value) {
el.outerHTML = dir.value
}
}
})
|