防抖throttle
防抖:当事件在短时间内持续触发,在间隔时间内(如1000ms),只在最后一次触发的时候,执行目标函数。
就是说,防抖不会让函数立即执行,而是1000ms延时内没有再次触发,才会执行目标函数
实现:通过setTimeout做延时处理,如果定时器不为空,则重新延时。
应用场景:监听输入框keyup。
//防抖
function debounce(fn,delay){
let timer = null //借助闭包
return function() {
if(timer){
clearTimeout(timer)
}
timer = setTimeout(fn,delay) // 简化写法
}
}
//目标函数
function handle(){
console.log(Math.random())
}
//监听防抖
window.onscroll = debounce(handle,1000)
以上代码的效果就是,在滚动条停止一秒滚动之后,才会执行一次函数,输出一个随机数。
节流debounce
节流:函数间隔一段时间后才能再触发,避免某些函数触发频率过高。
就是说,保证目标函数在间隔时间(如1000ms)内只执行一次
实现:一定时间内只触发一次函数,通过判断是否达到一定时间来确定是否要执行目标函数。
应用场景:防止频繁点击造成表单多次提交,监听滚动事件。
//节流
function throttle(fn,delay){
let valid = true
return function() {
if(!valid){
//休息时间 暂不接客
return false
}
// 工作时间,执行函数并且在间隔期内把状态位设为无效
valid = false
setTimeout(() => {
fn()
valid = true;
}, delay)
}
}
//目标函数
function handle(){
console.log(Math.random())
}
//监听节流
window.onscroll = throttle(handle,1000)
以上代码的效果就是,当滚动条一直处于滚动状态时,每隔一秒输出一个随机数。
总结:(当持续触发时)防抖让事件只在最后一次发生。节流让事件每隔一段时间触发一次
然后看看vue的官方文档里面提到的使用lodash库来实现防抖的。vue在watch时使用防抖
<!-- 提供这些功能以保持精简。这也可以让你自由选择自己更熟悉的工具。 -->
<script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
<script>
var watchExampleVM = new Vue({
el: '#watch-example',
data: {
question: '',
answer: 'I cannot give you an answer until you ask a question!'
},
watch: {
// 如果 `question` 发生改变,这个函数就会运行
question: function (newQuestion, oldQuestion) {
this.answer = 'Waiting for you to stop typing...'
this.debouncedGetAnswer()
}
},
created: function () {
// `_.debounce` 是一个通过 Lodash 限制操作频率的函数。
// `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识,
// 请参考:https://lodash.com/docs#debounce
this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
},
methods: {
getAnswer: function () {
//do something...
}
}
})
</script>
可以发现有了lodash这个JavaScript库之后,要写节流可防抖是非常方便的。
然后看看lodash里面关于防抖debounce和节流throttle的相关介绍吧。
防抖debounce
_.debounce(func, [wait=0], [options={}])
debounce的参数
func (Function): 要防抖动的函数。
[wait=0] (number): 需要延迟的毫秒数。
[options={}] (Object): 选项对象。
[options.leading=false] (boolean): 指定在延迟开始前调用。
[options.maxWait] (number): 设置 func 允许被延迟的最大值。
[options.trailing=true] (boolean): 指定在延迟结束后调用。
// 避免窗口在变动时出现昂贵的计算开销。
jQuery(window).on('resize', _.debounce(calculateLayout, 150));
节流throttle
_.throttle(func, [wait=0], [options={}])
throttle的参数
func (Function): 要节流的函数。
[wait=0] (number): 需要节流的毫秒。
[options={}] (Object): 选项对象。
[options.leading=true] (boolean): 指定调用在节流开始前。
[options.trailing=true] (boolean): 指定调用在节流结束后。
// 避免在滚动时过分的更新定位
jQuery(window).on('scroll', _.throttle(updatePosition, 100));
我大概看了一下lodash的官方文档,很丰富耶,感觉如果用这个js库的话可以省事又规范,找时间看一哈。