本文目录
  1. 防抖
    1. 搜索框带来的问题
    2. 实现的思路
    3. 案例
    4. 封装防抖函数
  2. 节流
    1. 滚动条加载带来的问题
    2. 实现的思路
    3. 案例
    4. 封装节流函数
公告
淡泊明志,宁静致远
网站资讯
本站文章字数合计
282.8k
本站Hexo版本
6.1.0
本站Node版本
16.20.2
本站已运行时间
最后更新时间

分类: web前端 | 标签: 防抖 节流

js的防抖和节流

发表于: 2023-02-12 10:09:09 | 字数统计: 1.3k | 阅读时长预计: 6分钟

B站视频教程: JS_防抖_节流

防抖

搜索框带来的问题

需求:根据输入框内容来请求数据

<!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>
<body>
    <input id="searchTxt" type="search" placeholder="请输入关键字检索">
    <script>
        document.querySelector("#searchTxt").oninput = function(){
            console.log('发送请求,当前输入框值:',this.value)
        }
    </script>
</body>
</html>

上面的代码会带来一个问题:用户每输入一个关键字都会触发

image-20230212103615638

现在是要求是用户停下来不输入的时候再触发一次,这个时候就需要用到防抖函数了

实现的思路

  1. 事件函数执行,先创建个定时器
  2. 逻辑代码放到定时器
  3. 当函数再次触发,清除定时器
  4. 创建一个新定时器即可

案例

<!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>
<body>
    <input id="searchTxt" type="search" placeholder="请输入关键字检索">
    <script>
        let t = null
        document.querySelector("#searchTxt").oninput = function(){
            clearTimeout(t) //有定时器则清除
            t = setTimeout(() => {
                console.log('发送请求,当前输入框值:',this.value)
            }, 1000);
        }
    </script>
</body>
</html>

image-20230212104119184

封装防抖函数

<!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>
<body>
    <input id="searchTxt" type="search" placeholder="请输入关键字检索">
    <script>
        document.querySelector("#searchTxt").oninput = debounce(function(){
            console.log('发送请求,当前输入框值:',this.value)
        })
        //封装一个公共的防抖函数
        function debounce(fn){//将函数逻辑放入fn中
            let t = null //此处利用闭包保存定时器
            return function(){
                clearTimeout(t) //有定时器则清除
                t = setTimeout(() => {
                    //箭头函数指向外面函数的this,而外面函数由input触发
                    fn.call(this) //利用call改变fn的this,否则fn的this为undefined
                }, 1000);
            }
        }
    </script>
</body>
</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>
    <style>
        .box{
            height: 1000px;
        }
    </style>
</head>
<body>
    <div class="box">

    </div>
    <script>
        document.onscroll = function(){
            console.log('发送ajax,请求下一页数据')
        }
    </script>
</body>
</html>

上面的代码会带来一个问题:用户轻轻下拉滚动条,onscroll中的逻辑会触发很多次

image-20230212111058652

现在是要求是降低触发事件的频率,这个时候就需要用到节流函数了。

实现的思路

  1. 事件函数执行,先判断是否有定时器,有则直接return
  2. 把逻辑代码放到定时器
  3. 定时器执行后,置空定时器变量

案例

<!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>
    <style>
        .box{
            height: 1000px;
        }
    </style>
</head>
<body>
    <div class="box"></div>
    <script>
        let t = null
        document.onscroll = function(){
            if(null != t) return //关键点1:有定时器则return
            t = setTimeout(() => {//关键点2:逻辑代码放到定时器中
                console.log('发送ajax,请求下一页数据')
                t = null  //关键点3:定时器执行完毕,置空定时器变量
            }, 500);
        }
    </script>
</body>
</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>
    <style>
        .box{
            height: 1000px;
        }
    </style>
</head>
<body>
    <div class="box"></div>
    <script>
        
        document.onscroll = throttle(function () {
            console.log('发送ajax,请求下一页数据',this)
        })

        //封装一个节流函数
        function throttle(fn) {
            return function(){
                //这里用的是fn.t变量的形式来保存定时器变量
                if(null != fn.t) return 
                fn.t = setTimeout(() => {
                    fn.call(this)
                    fn.t = null
                }, 500);
            }
        }
    </script>
</body>
</html>
------ 本文结束,感谢您的阅读 ------
本文作者: 程序员青阳
版权声明: 本文采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。