防抖和节流就是为了限制函数执行的次数,减少请求量,进行优化。
防抖(debounce)
什么是防抖?
触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间。
例子:
鼠标进入box
内移动,每次移动都+1
<style>
.box {
width: 100%;
height: 300px;
background-color: plum;
font-size: 20px;
text-align: center;
line-height: 300px;
}
</style>
<div class="box">0</div>
<script>
let count = 0;
let box = document.querySelector(".box");
function move() {
box.innerHTML = count++;
}
box.onmousemove = move;
</script>
高频触发事件,当鼠标进入盒子内之后,每移动一次,就会让box
中的数字+1
,非常的耗性能。
使用防抖函数,在1s内没有再次的进行移动鼠标,时间结束后,才会输出;如果在1s内继续移动鼠标,则时间会重新计时,再次从1s开始计算,直到没有移动的操作,才会输出。
封装函数
function debounce(fn) {
let time = null; //设置定时的名字,通过闭包进行保存名字
return function () {
clearTimeout(time); // 让前一个定时器 清除掉 重新计算时间
// 如果只用定时器 只是起到了 延迟输出的作用
time = setTimeout(function () {
// this 改变this指向,指向当前作用的对象box
// arguments 指向event对象
fn.apply(this,arguments);
}, 1000)
}
}
// 调用函数,每次移动都调用debounce函数,清除上次的定时器,在重新赋值一个定时器,用来计算时间
box.onmousemove = debounce(move);
事件响应函数(move函数)
在一段时间后(1000ms)
才执行
如果在这段时间内(1000ms内)
再次调用,则会重新计算执行时间。
当预定时间内(1000ms)
,没有再次调用该函数 则会执行事件函数(move函数)
。
延后的概念
节流(throttle)
什么是节流?
高频事件触发,但是在n秒内只会执行一次,所以节流会稀释函数的执行频率
(可以简易理解成节流阀
,当设置节流阀之后,在规定的时间
内,不能
执行下次的函数程序。)
举个例子:
当改变窗口大小
的时候,让body
的背景颜色也随之改变。
<script>
function color() {
let r = Math.floor(Math.random() * 255);
let g = Math.floor(Math.random() * 255);
let b = Math.floor(Math.random() * 255);
document.documentElement.style.backgroundColor = `rgb(${r},${g},${b})`
}
window.onresize=color;
</script>
执行效果是每改变一次,就改变body
的背景颜色;当快速改变的时候,颜色变换的很快,影响体验。
所以 使用节流函数
来对代码进行优化。
节流函数封装
function throttle(fn,dealy) {
let isTrue = true;//通过闭包设置的一个标记,为公用的
return function () {
if (!isTrue) return;// 判断标记是否为true,不为true就不执行下面的代码
isTrue = false;// 进来之后,使标记变为false,在定时器没有执行完之前,改变窗口大小函数不执行
setTimeout(() => {
fn.apply(this, arguments);
//关键在第一个参数,为了确保上下文环境为当前的this,所以不能直接用fn。
isTrue = true;// 执行完之后变为true,以方便进行下一个的调用
}, dealy)
}
}
// 函数调用
window.onresize = throttle(color,2000);
可以在函数封装中在设置一个dealy
参数,用于自己设置需要等待的时间。
应用的场景:
- 滚动事件
- resize事件,浏览器窗口缩放
- 搜索框输入查询
- 表单验证
- 按钮提交事件
- ....