防抖
概念: 指的是延迟规定的动作,若在延迟时间内,再次触发了,就会重新计时
这一般应用于输入框搜索的时候,进行搜索优化,不能在用户输入未结束时就请求后台,会使服务器压力过大
代码演示:
<!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>
<div>
<input type="text" id="inputD">
</div>
</body>
<script>
//防抖,指的是在事件执行n秒之后执行回调,当在n秒内又被触发,则重新计时
//辅助方式 setTimeout
let inputD = document.getElementById('inputD');
//添加事件
inputD.addEventListener('keyup', function() {
//获取输入值
let value = inputD.value;
mockAjax(value);//没加防抖之前
})
//模拟请求
function mockAjax(params) {
console.log('发送请求', params);
}
</script>
</html>
这是没加防抖操作之前的,此时会发现每次键入字符都会输出:
发送请求 w
发送请求 ww
发送请求 www
此时加入防抖:
1.加入定时器,此时只是延迟发生了,还是会触发三次
inputD.addEventListener('keyup', function() {
//获取输入值
let value = inputD.value;
// mockAjax(value);//没加防抖之前
setTimeout(() => {
mockAjax(value)
}, 500);
})
2.因为它多次触发,那就需要clearTimeout方法来清除定时器
这时候想到了防抖的含义,不就是每次触发的时候,重新计时吗,那么,我定义一个全局的定时器id,是做防抖的定时器,在触发的方法内部清除掉id,那么不就是又重新计时了.而且clearTimeout方法兼容性很好,当我传一个null参数,也不会报错.所以最后的代码如下
let inputD = document.getElementById('inputD');
//添加事件
let id = null;
inputD.addEventListener('keyup', function() {
//获取输入值
let value = inputD.value;
// mockAjax(value);//没加防抖之前
clearTimeout(id);//删除计时器,重新计时
id = setTimeout(() => {
mockAjax(value)
}, 500);
})
//模拟请求
function mockAjax(params) {
console.log('发送请求', params);
}
这时候去页面上请求,会发现,不会每个字符都打印,除非你键入一个字符停留的时间超过500ms
发送请求 ww
发送请求 wwwww
发送请求 wwwwwas
节流
概念: 设定一个时间段,在这个时间段内,让函数只执行一次
一般在实际开发中使用的比较少,但是面试会作为一个防抖连带的问题提出.
这里使用一个滚轮事件做说明
需求:当滚轮滚动的时候,每2s输出一次
<!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>
<style>
body {
height: 2000px;
}
</style>
<body>
</body>
<script>
//函数节流:设定一个时间,让函数在特定的时间内只执行一次,不会频繁执行
//辅助:setTimeout flag
let body = document.getElementsByTagName('body')[0];
body.onscroll = () => {
//未节流之前
console.log('触发打印');
}
</script>
</html>
此时控制台输出n次的’触发打印’
下面进行节流操作
1.加定时器,定时2秒钟触发打印一次,但是会发现它只是延迟输出了,2s内滑动鼠标还是会打印很多次
let body = document.getElementsByTagName('body')[0];
body.onscroll = () => {
//未节流之前
setTimeout(() => {
console.log('触发打印');
}, 2000);
}
2.加标识,flag定义为是否到2s
考虑一下,setTimout执行的时候,刚好是2s,这时候将flag改变状态,这时候又重新开始计时了,等到2s之后触发打印函数
let body = document.getElementsByTagName('body')[0];
let flag = true; //节流标识,是否到两秒 默认是true,第一次要进入到if里面
body.onscroll = () => {
if (flag) {
flag = false;
//如果到2s 触发函数
setTimeout(() => {
flag = true; //改变状态
console.log('触发打印');
}, 2000);
}
这个时候回到页面上滑动测试,会发现是定时输出的
两者的区别
- 防抖是为了使高频函数减少执行的次数的
- 节流是时间段内只执行一次,让高频函数只执行一次
END