vue自定义指令:防抖与节流
防抖
解释:触发事件后,一段时间内没有再次触发则执行,若此时间段内再次触发重新延时!
v-antiShake
// 实现
vue.directive('antiShake', {
// 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
/**
* el 指令所绑定的元素,可以用来直接操作 dom 。
* binding 一个对象,包含绑定的值
*/
inserted: function(el, binding) {
const { callback, time } = binding.value
el.callback = callback
el.time = time
el.timeCall = null
el.addEventListener('click', () => {
clearTimeout(el.timeCall)
el.timeCall = setTimeout(() => {
el.callback()
}, el.time || 500)
})
},
// 所在组件的 VNode 更新时调用
update: function(el, binding) {
console.log('update')
const { callback, time } = binding.value
el.callback = callback
el.time = time
},
})
核心原理
const { callback, time } = binding.value
el.callback = callback
el.time = time
el.timeCall = null
el.addEventListener('click', () => {
clearTimeout(el.timeCall)
el.timeCall = setTimeout(() => {
el.callback()
}, el.time || 500)
})
通过定时器setTimeout延时执行click回调,当el.time || 500 时间内,再次触发时 clearTimeout(el.timeCall)关闭定时器,再次重新延时
el.callback = callback 和 el.time = time 挂在el上是为了,当v-antiShake绑定的值更新后,事件触发更新后的callback
update: function(el, binding) {
console.log('update')
const { callback, time } = binding.value
el.callback = callback
el.time = time
},
使用
指令的值testClick未做深watch,只有对象整体改变才会触发指令中update钩子函数
<button v-antiShake="testClick">click</button>
// testClick
testClick: {
time: 1000,
callback: () => {
console.log(1111)
console.log(this.test)
}
}节流
一段时间内首次触发时立即执行,此时间段内再次触发,不会执行!
实现:
Vue.directive('throttling', {
// 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
inserted: function(el, binding) {
const { callback, time } = binding.value
el.callback = callback
el.time = time
el.addEventListener('click', () => {
const nowTime = new Date().getTime()
if (!el.preTime || nowTime - el.preTime > el.time) {
el.preTime = nowTime
el.callback()
}
})
},
update: function(el, binding) {
console.log('update')
const { callback, time } = binding.value
el.callback = callback
el.time = time
}
})
el.preTime 记录上次触发事件,每次触发比较nowTime(当前时间) 和 el.preTime 的差是否大于指定的时间段!
本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!