定义
1、防抖函数定义
- 防抖(debounce):触发高频事件后 n 秒内函数只会执行一次,如果 n 秒内高频事件再次被触发,则重新计算时间
举例说明:
举例:就好像在百度搜索时,每次输入之后都有联想词弹出,这个控制联想词的方法就不可能是输入框内容一改变就触发的,他一定是当你结束输入一段时间之后才会触发。
2、防抖函数的封装
需求:
- 持续触发不执行
- 不触发的一段时间之后再执行
思路:
- 那么怎么实现上述的目标呢?我们先看这一点:在不触发的一段时间之后再执行,那就需要个定时器呀,定时器里面调用我们要执行的函数,将arguments传入。
- 封装一个函数,让持续触发的事件监听是我们封装的这个函数,将目标函数作为回调(func)传进去,等待一段时间过后执行目标函数
- 第二点实现了,再看第一点:持续触发不执行。我们先思考一下,是什么让我们的函数执行了呢?是上边的setTimeout。OK,那现在的问题就变成了持续触发,不能有setTimeout。这样直接在事件持续触发的时候,清掉定时器就好了。
封装:
function debounce(fn, delay) {
let timer = null
return function () {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
//模拟触发change事件
fn.apply(this, arguments)
// 清空计时器
timer = null
}, delay);
}
}
3、利用防抖函数的实例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- DOM元素 -->
<input id="input1" type="text">
<script>
//防抖函数
const input1 = document.getElementById('input1')
function debounce(fn, delay) {
let timer = null
return function () {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
//模拟触发change事件
fn.apply(this, arguments)
// 清空计时器
timer = null
}, delay);
}
}
input1.addEventListener('keyup', debounce(() => {
console.log(input1.value)
}, 500))
// input1.οnkeyup=function(){
// console.log(input1.value);
// }
</script>
</body>
</html>
展示结果:
小结:
如上图所示,我们需要监听输入框里面的value值将其传递给后台,用户输入的每一次都将发送给后台,那么就会造成网络的堵塞,浪费资源,我们封装一个防抖函数,在规定的时间内,获取输入框的值,若期间多次重复输入的话,每一次输入,我们就会重新计算时间,知道最后一次触发该事件,那么防抖函数就有效的解决了这个问题!
4、节流函数定义
- 节流(thorttle):高频事件触发,但在 n 秒内只会执行一次,所以节流会稀释函数的执行频率
举例说明:
举例:预定一个函数只有在大于等于执行周期时才执行,周期内调用不执行。就好像你在淘宝抢购某一件限量热卖商品时,你不断点刷新点购买,可是总有一段时间你点上是没有效果,这里就用到了节流,就是怕点的太快导致系统出现bug。
5、节流函数的封装
需求
- 持续触发并不会执行多次
- 到一定时间再去执行
思路
- 思考一下,持续触发,并不会执行,但是到时间了就会执行。抓取一个关键的点:就是执行的时机。要做到控制执行的时机,我们可以通过一个开关,与定时器setTimeout结合完成。
- 函数执行的前提条件是开关打开,持续触发时,持续关闭开关,等到setTimeout到时间了,再把开关打开,函数就会执行了。
- 这样,就实现了节流,节流还可以用时间间隔去控制,就是记录上一次函数的执行时间,与当前时间作比较,如果当前时间与上次执行时间的时间差大于一个值,就执行。
封装
function throttle(fn, delay = 100) {
let timer = null
return function () {
if (timer) {
return
}
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
}, delay);
}
}
6、利用节流函数的实例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- //DOM元素 -->
<div id="div1" draggable="true" style="width:100px;height:100px;background:pink">可拖拽</div>
<script>
//节流函数
const div1 = document.getElementById('div1')
function throttle(fn, delay = 100) {
let timer = null
return function () {
if (timer) {
return
}
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
}, delay);
}
}
div1.addEventListener('drag', throttle(function (e) {
console.log(e.offsetX, e.offsetY)
}, 200))
</script>
</body>
</html>
展示结果:
小结:
如上图所示,鼠标拖动物块儿,我们打印出它的位置坐标,我们监听鼠标移动事件,若没有节流函数的辅助,那么只要鼠标一拖动,那么控制台就会持续输出他的位置坐标,为了防止控制台监听打印我们不需要的数据,节流函数,有效的结局了控制台持续输出的问题,让其在规定的时间内输出一次该坐标,每次移动控制台有规律的输出当前的坐标!
7、防抖函数和节流函数有什么区别呢(一句话概括)?
区别:防抖动是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行。