防抖(debounce)

防抖的应用场景

  1. scroll事件滚动触发
  2. 搜索框输入查询
  3. 表单验证
  4. 按钮提交事件
  5. 浏览器窗口缩放,resize事件

防抖的原理

原理:n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时

举例:
事件响应函数在一段时间后才执行,如果在这段事件内再次调用,则重新计算执行时间;当预定的时间内没有再次调用该函数,则执行dosomething函数。

<style>
    #container{
    
    
        width: 100%;
        height:200px;
        line-height: 200px;
        text-align: center;
        color:#fff;
        background-color: #444;
        font-size: 30px;
    }
</style>
<body>
    <div id="container"></div>
    //引入underscore库,其中的debounce可以实现防抖
    <script src="http://cdn.bootcss.com/underscore.js/1.9.1/underscore.js"></script>
    <script>
        let count = 0
        //演示时间是如何频繁发生的
        let container  = document.querySelector('#container')

        function doSomeThing(){
    
    
            //可能会做回调或者ajax请求
            container.innerHTML = count++;
        }
        //_.debounce(高阶函数)对doSomething函数进行包装,第一个参数为被包装函数的函数名,第二个参数为时间,表示多少毫秒后执行
        //第三个参数表示是否立即执行,如果设置true表示立即执行,默认值是不会立即执行container.onmousemove = _.debounce(doSomeThing,2000,true);
        container.onmousemove = _.debounce(doSomeThing,2000);
    </script>
</body>

防抖的分类

防抖分为立即防抖非立即防抖

  • 立即防抖:多次触发事件,第一次会立即执行函数,之后在设定wait时间内触发的事件无效,不会执行。

  • 非立即防抖:多次触发事件,只会在最后一次触发事件后等待设定的wait时间结束时执行一次。

手写防抖函数(debounce)

初步实现防抖函数:

index.html文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>
    #container{
    
    
        width: 100%;
        height:200px;
        line-height: 200px;
        text-align: center;
        color:#fff;
        background-color: #444;
        font-size: 30px;
    }
</style>
<body>
    <div id="container"></div>
    <!-- //引入debounce.js文件 -->
    <script src="./debounce.js"></script>
</body>
</html>

js文件:

//防抖的函数
//这里用到了闭包
function debounce(func,wait,immediate){
    
    
    let timeout;
    return function(){
    
    
        //改变执行函数内部this的指向,让this指向container
        let context = this;
        //参数
        let args = arguments;
        clearTimeout(timeout)//只清除定时器,不清除timeout的值
        if(immediate){
    
    
            //立即执行:多次触发事件,第一次会立即执行函数,之后在设定wait时间内触发的事件无效,不会执行。
            //callNow来记录是否立即执行,callNow为true立即执行
            let callNow = !timeout;
            //wait时间内(timeout有值,callNow为false)不会立即执行
            //wait时间到了(timeout值置为null,callNow为true)立即执行
            timeout = setTimeout(()=>{
    
    
                timeout = null;
            },wait);
            if(callNow){
    
    
                func.apply(context,args)
            }
        }else{
    
    
            //非立即执行:多次触发事件,只会在最后一次触发事件后等待设定的wait时间结束时执行一次。
            timeout = setTimeout(()=>{
    
    
                func.apply(context,args)
            },wait)
        }
    }
}
let count = 0;
//演示时间是如何频繁发生的
let container = document.querySelector("#container");

function doSomeThing() {
    
    
  //可能会做回调或者ajax请求
  container.innerHTML = count++;
}
container.onmousemove = debounce(doSomeThing, 300,true);

防抖函数中返回值和取消操作的实现:

扫描二维码关注公众号,回复: 14790589 查看本文章

index.html文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>
    #container{
    
    
        width: 100%;
        height:200px;
        line-height: 200px;
        text-align: center;
        color:#fff;
        background-color: #444;
        font-size: 30px;
    }
</style>
<body>
    <div id="container"></div>
    <button id="btn">取消防抖</button>
    <!-- //引入debounce.js文件 -->
    <script src="./debounce.js"></script>
</body>
</html>

js文件:

//防抖的函数
function debounce(func,wait,immediate){
    
    
    var timeout,result;
    var debounced = function(){
    
    
        //改变执行函数内部this的指向,让this指向container
        var context = this;
        //参数
        var args = arguments;
        if(timeout) clearTimeout(timeout);
        if(immediate){
    
              
            var callNow = !timeout;
            timeout = setTimeout(()=>{
    
    
                timeout = null;
            },wait);
            if(callNow){
    
    
                result = func.apply(context,args)
            }
        }else{
    
    
            timeout = setTimeout(()=>{
    
    
                func.apply(context,args)
            },wait)
        }
        return result;
    }
    //取消防抖
    debounced.cancel = function(){
    
    
        clearTimeout(timeout)
        //防止内存泄露
        timeout = null;
    }
    return debounced;
}
let count = 0;
//演示时间是如何频繁发生的
let container = document.querySelector("#container");
let btn = document.querySelector('#btn')
function doSomeThing() {
    
    
  //可能会做回调或者ajax请求
  container.innerHTML = count++;
  return '想要的结果'
}
let doSome = debounce(doSomeThing,1000);
//点击按钮,取消防抖
btn.onclick = function(){
    
    
    doSome.cancel()
}
//给container绑定鼠标移动事件
container.onmousemove = doSome;

猜你喜欢

转载自blog.csdn.net/weixin_52148548/article/details/125170284
今日推荐