目标
1.什么是防抖和节流
2.防抖和节流的实现
什么是防抖和节流
函数防抖(debounce):当持续触发事件时,一定时间内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,有一次触发了事件,就重新开始延时。
前端开发过程中的resize,scroll,mousemove,mousehover等,会频繁地触发,不做限制的话,有可能一秒之内执行几十次、几百次,如果再这些函数内部执行了其他函数,尤其是执行了操作DOM的函数,那不仅会造成计算机资源的浪费,还会降低程序运行速度,甚至造成浏览器卡死,崩溃。
“函数防抖”的关键在于,再一个动作发生一定时间之后,才执行特定事件
防抖和节流的实现
普通的事件触发如下
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<title>debounce</title>
<meta name='viewport' content='width=device-width, initial-scale=1,user-scalable=no;'>
<link rel='stylesheet' type='text/css' media='screen' href='main.css'>
<script src='main.js'></script>
<style>
*{
margin:0;
padding:0;
}
#content{
width:200px;
height:200px;
line-height:200px;
background-color: #ccc;
margin:0 auto;
font-size:60px;
text-align:center;
color:#000;
cursor:pointer;
}
</style>
</head>
<body>
<div id="content"></div>
</body>
<script>
let num = 1;
let oDiv = document.getElementById('content');
let changeNum = function(){
oDiv.innerHTML = num + 1;
}
oDiv.onmousemove = changeNum;
</script>
</html>
而使用防抖函数如下:
let deBounce = (fn,delay)=>{
let time = null;
return function(){
if(timer){
clearTimeout(timer);
}
setTimeout(function(){
fn();
},delay)
}
}
oDiv.onmousemove = deBounce(changeNum,500);
但上述函数的setTimeout作用域时window,而我们只需要作用再content的div上,所以使用箭头函数来指定
let deBounce = (fn,delay)=>{
let time = null;
return function(){
if(timer){
clearTimeout(timer);
}
setTimeout(()=>{
fn();
},delay)
}
}
oDiv.onmousemove = deBounce(changeNum,500);
因为箭头函数没有自己的this作用域,它的this时来源于作用域链,同时它也没有自己的argument,但我们需要绑定argument的时候,可以通过扩展运算符来绑定
let deBounce = (fn,delay)=>{
let time = null;
return function(...args){
if(timer){
clearTimeout(timer);
}
setTimeout(()=>{
fn(...args);
},delay)
}
}
oDiv.onmousemove = deBounce(changeNum,500);
以上就是简单的防抖函数
函数防抖存在的问题
如果?一直触发事件,且每次触发事件的间隔小于delay
函数节流
函数节流(throttle):当持续触发事件时,保证一定时间段内指调用一次事件处理函数
let oButton = document.getElementsByTagName('button')[0];
let fn =() => {
console.log('我被响应了');
}
let throttle = (fn,delay)=>{
let flag = true;
return function(...args){
if(!flag) return;
flag = false;
setTimeout(() => {
fn(...args);
flag = true;
},delay)
}
}
oButton.onclick = throttle(fn,500);
防抖和节流在开发中的使用场景
let oInput = document.getElementsByTagName('input')[0];
let ajax = (content) => {
let message = content;
let json = {message};
console.log(Json.stringify(json));
}
let doAjax = deBounce(ajax,2000);
//不使用防抖
oInput.addEventListener('keyup',(e) =>{
console.log(e.target.value)
})
//使用防抖
oInput.addEventListener('keyup',(e) =>{
doAjax(e.target.value);
})