防抖与节流(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 的差是否大于指定的时间段!