【前言】

在工作中,我们可能碰到这样的问题:

  • 用户在搜索的时候,在不停敲字,如果每敲一个字我们就要调一次接口,接口调用太频繁,给卡住了。
  • 用户在阅读文章的时候,我们需要监听用户滚动到了哪个标题,但是每滚动一下就监听,那样会太过频繁从而占内存,如果再加上其他的业务代码,就卡住了。

所以,这时候,我们就要用到 防抖与节流 了。

那么,讲到 防抖与节流,我们可以顺带探秘下 重绘与回流

说起 重绘与回流,我们就顺带把 浏览器输入 URL 后发生的事情 也关注一下,从而引出 DNSTCP 等知识点,最终串起来构成本文的轮廓,方便 jsliang 和小伙伴们对这块知识的整理与记忆。

【主体】

本节主要介绍函数防抖debounce

下面我们有段防抖小案例代码。

如果小伙伴们手头有电脑,并感兴趣想先自己思考下什么是防抖。可以将代码复制到浏览器,尝试点击按钮,并关注下控制台,看看 Console 是如何打印的。

如果小伙伴们手头没有电脑,那么咱一起先瞅瞅代码实现,再看看下面 GIF 演示。(这样效果没有自己敲的直白有效)

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>防抖</title>
</head>
<body>
<button id="debounce">点我防抖!</button> <script>
window.onload = function() {
// 1、获取这个按钮,并绑定事件
var myDebounce = document.getElementById("debounce");
myDebounce.addEventListener("click", debounce(sayDebounce));
} // 2、防抖功能函数,接受传参
function debounce(fn) {
// 4、创建一个标记用来存放定时器的返回值
let timeout = null;
return function() {
// 5、每次当用户点击/输入的时候,把前一个定时器清除
clearTimeout(timeout);
// 6、然后创建一个新的 setTimeout,
// 这样就能保证点击按钮后的 interval 间隔内
// 如果用户还点击了的话,就不会执行 fn 函数
timeout = setTimeout(() => {
fn.call(this, arguments);
}, );
};
} // 3、需要进行防抖的事件处理
function sayDebounce() {
// ... 有些需要防抖的工作,在这里执行
console.log("防抖成功!");
} </script>
</body>
</html>

很好,相信小伙伴们已经看完了代码,下面我们看看它的演示:

浅谈JS函数防抖及应用场景-LMLPHP

这时候,我们可以抛出防抖的概念了:

  • 防抖任务频繁触发的情况下,只有任务触发的间隔超过指定间隔的时候,任务才会执行。

结合上面的代码,我们可以了解到,在触发点击事件后,如果用户再次点击了,我们会清空之前的定时器,重新生成一个定时器。意思就是:这件事儿需要等待,如果你反复催促,我就重新计时!

空讲无益,show you 场景:

  • 有个输入框,输入之后会调用接口,获取联想词。但是,因为频繁调用接口不太好,所以我们在代码中使用防抖功能,只有在用户输入完毕的一段时间后,才会调用接口,出现联想词。

小伙伴们可以尝试看着上面的案例,先自己实现一遍这个场景的解决,如果感觉不行,那就看:《防抖和节流的应用场景和实现》

 
案例2:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>demo</title>
</head>
<body>
<input type="text" name="search"> <script type="text/javascript">
var searchInput = document.querySelector('input[name="search"]');
/*绑定事件*/
searchInput.addEventListener('keyup',debounce(getInputValue),false);
/* 防抖函数 */
function debounce(fn){
var timer = null;
return function(){
if(timer){
clearTimeout(timer)
}
timer = setTimeout(()=>{
fn.call(this,arguments)
},)
}
}
/* 调用获取输入值 */
function getInputValue(){
console.dir(this.value)
}
</script>
</body>
</html>

.

05-11 11:33