浅谈 JavaScript 中的防抖与节流(一)
简介
防抖与节流都是用来限制用户频发触发事件的机制,下面我将简单介绍一下,防抖与节流的区别及其应用场景
防抖
当用户触发某次事件后,若在规定时间内不再触发该事件,则这个事件才会被真正响应。我们称这样的机制为防抖
举例说明
现规定一辆大巴,从最后一位上车人的时间算起,在等待十分钟后,才允许发车。
若我们设定最后一个上车人的时间设为Tn,那么发车的时间则为Tn + 10min。
在上述例子中,我们不难发现,大巴发车的时间是不固定的,是随着最后一位上车人的时间而动态改变的。如果大巴在等待发车的过程中,不断有人上车,那么大巴真正的发车时间则不断向后推移,并且始终与最后一位上车人的时间保持着十分钟的时间差。
触发与响应
我们可以将人上车
这一动作比作事件的触发,而大巴发车
则比作事件的响应。在防抖
机制里面,事件的响应时间
(也就是事件真正开始执行的时间)是随这个事件最后被触发的时间
而发生变化的。
我们再做一个假设,现有一个按钮,当用户点击这个按钮时,并且要求在十秒内不再点击这个按钮,才会向后台发送请求。
我们设定观察时间为三十秒,T代表用户点击按钮,R代表向后台发送请求
一、若用户每隔五秒点击一次按钮,则事件触发与响应示例图如下:
由上图,我们可以看到,因为用户每次点击按钮的时间间隔不足十秒,所以在这观察的三十秒内并不会有向后台发送的请求。
二、若用户每隔十五秒点击一次按钮,则事件触发与响应示例图如下:
而这一次,当我们将用户每次点击按钮的时间间隔保持在十秒以上时,则一共向后台发送了两次请求:R1和R2。
代码示例
只要简单的几行代码便可实现防抖机制
/**
* @desc 函数防抖
* @param func 函数
* @param wait 延迟执行毫秒数
*/
function debounce(func, wait) {
let timeout;
return function () {
let context = this
let args = arguments
if (timeout) clearTimeout(timeout)
timeout = setTimeout(function() {
func.apply(context, args)
}, wait)
}
}
Tips:
apply()
方法是用来改变this
指向的
在JavaScript中,防抖
主要是通过setTimeout
来实现的。当事件被触发时,则创建一个计时器,只有当约定的时间到了才会真正执行事件,但是当事件还未执行,而这个事件又再次被触发了,则将上一计时器清除,重新创建一个新计时器,也就是重新计算时间的意思。
在Vue中的使用
以Vue为例,实现我们开头举的大巴发车的例子
<template>
<div id="app">
<button @click="addPeople">有人上车</button>
<h1>发车次数:{{ runNum }}</h1>
<h1>车上人数:{{ people }}</h1>
<h1>距离最后一个人上车已等待:{{ time }}秒</h1>
</div>
</template>
<script>
/**
* @desc 函数防抖
* @param func 函数
* @param wait 延迟执行毫秒数
*/
function debounce(func, wait) {
let timeout
return function () {
let context = this
let args = arguments
if (timeout) clearTimeout(timeout)
timeout = setTimeout(function() {
func.apply(context, args)
}, wait)
}
}
export default {
data() {
return {
runNum: 0, // 发车次数
people: 0, // 上车人数
time: 0,
interval: ''
}
},
watch: {
people: debounce(function (val) {
this.runNum++
clearInterval(this.interval)
}, 10000)
},
methods: {
addPeople () {
this.clearTime()
this.people++
this.startTime()
},
startTime () {
this.interval = setInterval(() => {
this.time++
}, 1000)
},
clearTime () {
this.time = 0
clearInterval(this.interval)
}
}
}
</script>
参考来源
本作品采用《CC 协议》,转载必须注明作者和本文链接