vue自定义指令
vue自定义指令有全局注册和局部注册两种方式
全局注册
1
Vue.directive(id, [definition])
局部注册
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16<!-- 批量注册 -->
import copy from './copy'
import longpress from './longpress'
// 自定义指令
const directives = {
copy,
longpress,
}
export default {
install(Vue) {
Object.keys(directives).forEach((key) => {
Vue.directive(key, directives[key])
})
},
}注册之后使用在main.js
1
2
3
4<!-- main.js使用 -->
import Vue from 'vue'
import Directives from './directives/index'
Vue.use(Directives)
指令函数中提供的几个钩子函数(可选):
- bind: 只调用一次,指令第一次绑定到元素时调用,可以定义一个在绑定时执行一次的初始化动作
- inserted: 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)
- update: 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值
- componentUpdated: 被绑定元素所在模板完成一次更新周期时调用
- unbind: 只调用一次, 指令与元素解绑时调用
常使用的自定义指令
防抖指令 v-debounce
- 防止按钮在短时间内被多次点击,使用防抖函数限制规定时间内只能点击一次
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
30const debounce = {
inserted: function (el, binding) {
let timer;
<!-- keyup -->
el.addEventListener('click', () => {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
binding.value()
}, 1000)
})
},
}
export default debounce;
<!-- dom中使用 -->
<template>
<button v-debounce="debounceClick">防抖</button>
</template>
<script>
export default {
methods: {
debounceClick () {
console.log('只触发一次')
}
}
}
</script>
- 防止按钮在短时间内被多次点击,使用防抖函数限制规定时间内只能点击一次
实现一个图片懒加载指令,只加载浏览器可见区域的图片
- 实现一个图片懒加载指令,只加载浏览器可见区域的图片。
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85const LazyLoad = {
// install方法
install(Vue, options) {
const defaultSrc = options.default
Vue.directive('lazy', {
bind(el, binding) {
LazyLoad.init(el, binding.value, defaultSrc)
},
inserted(el) {
if (IntersectionObserver) {
LazyLoad.observe(el)
} else {
LazyLoad.listenerScroll(el)
}
},
})
},
// 初始化
init(el, val, def) {
el.setAttribute('src', val)
el.setAttribute('src', def)
},
// 利用IntersectionObserver监听el
observe(el) {
var io = new IntersectionObserver((entries) => {
const realSrc = el.dataset.src
if (entries[0].isIntersecting) {
if (realSrc) {
el.src = realSrc
el.removeAttribute('src')
}
}
})
io.observe(el)
},
// 监听scroll事件
listenerScroll(el) {
const handler = LazyLoad.throttle(LazyLoad.load, 300)
LazyLoad.load(el)
window.addEventListener('scroll', () => {
handler(el)
})
},
// 加载真实图片
load(el) {
const windowHeight = document.documentElement.clientHeight
const elTop = el.getBoundingClientRect().top
const elBtm = el.getBoundingClientRect().bottom
const realSrc = el.dataset.src
if (elTop - windowHeight < 0 && elBtm > 0) {
if (realSrc) {
el.src = realSrc
el.removeAttribute('src')
}
}
},
// 节流
throttle(fn, delay) {
let timer
let prevTime
return function (...args) {
const currTime = Date.now()
const context = this
if (!prevTime) prevTime = currTime
clearTimeout(timer)
if (currTime - prevTime > delay) {
prevTime = currTime
fn.apply(context, args)
clearTimeout(timer)
return
}
timer = setTimeout(function () {
prevTime = Date.now()
timer = null
fn.apply(context, args)
}, delay)
}
},
}
export default LazyLoad;
<!-- dom中使用 -->
<img v-LazyLoad="xxx.jpg" />
- 实现一个图片懒加载指令,只加载浏览器可见区域的图片。