前端面试必问的JS防抖如何实现

1,506 阅读3分钟

这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战

👨‍💻 博客主页:作者主页
👍 觉得文章不错的朋友可以点点赞和关注
🎁 粉丝福利:学习资料、简历模板统统都有点击领取

工作场景

有一个这样的需求,就是我们写一个类似于百度搜索这样的功能,我们输入一个关键字,下面会自动给我们返回带有关键字的这样一个需求,我们该怎么实现呢?

先看代码

<!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 {
            width: 100%;
            height: 100%;
            display: flex;
            justify-content: center;
            align-items: center;
        }
    </style>
</head>

<body>
    <div class="box">
        <div>
            <h1>百度sou索</h1>
            <input type="text" id="inputBox">
        </div>
    </div>
		<script>
        var inputBox = document.getElementById('inputBox')
        inputBox.addEventListener('input', () => {
            console.log('输入了内容并发送请求');
        })
    </script>
</body>

</html>

浏览器表现如下

思考一

我们在搜索框多次输入字段,每输入一个就会发送一个请求,这样非常的频繁请求,服务器的压力非常的大。这是非常不可取的,而且我们也许只是想获取我们想要的信息而已。

我只想知道123456,不想知道1是什么,12是什么等等

所以我们设置一个函数,就是想让用户输入完毕的时候,才发送请求

然后我们把代码写成下面这样了

var inputBox = document.getElementById('inputBox')

        function shake(fn) {  //接收一个参数fn

        }

        inputBox.addEventListener('input', shake(() => {
            console.log('输入了内容并发送请求');
       }))

我们将那个匿名函数作为一个参数传入到shake函数中,就是转变为,每次输入就触发一次这个函数,这样相比于上面好理解多了。

虽然它看起来好理解,但是总感觉好奇怪的,因为addEventListener第二个参数应该是一个函数,但是这里的值是由shake决定的,而且这个shake是返回的一个结果,如果它返回的不是函数,那就是非常的不对了,所以我们就改写成这样,让他返回一个函数

 var inputBox = document.getElementById('inputBox')

        function shake(fn) { //接收一个参数fn
            return function() {
                console.log('shake 这个函数执行了');
              	fn()
            }
        }

        inputBox.addEventListener('input', shake(() => {
            console.log('发送搜索框');
        }))

然后到页面上看一下

但是我们多次输入还是一样一直打印,然后我们可以给个定时器,让他等一下再去返回,看看效果如何。

var inputBox = document.getElementById('inputBox')

        function shake(fn) { //接收一个参数fn
            return function() {
                setTimeout(() => {
                    console.log('shake 这个函数执行了');
                    fn()
                }, 500)

            }
        }

        inputBox.addEventListener('input', shake(() => {
            console.log('发送搜索框');
        }))

然后我们再去浏览器控制台看一下

虽然他是延迟了执行,但是还是执行了多次,也就是我们无论触发多少次,最后到达时间还是执行一样的次数

为什么会这样呢?

原来是它触发了两次,只不过是延后执行,那么我们想要的效果是让他只返回一次,那么我们可以想,就是在进入之前,把上一个定时器销毁掉,只执行最后一个定时器,然后代码如下

var inputBox = document.getElementById('inputBox')



        function shake(fn) { //接收一个参数fn
            let timer = null;
            return function() {
                if (timer) {
                    clearTimeout(timer)
                }
                timer = setTimeout(() => {
                    console.log('shake函数执行了');
                    fn()
                }, 500)

            }
        }

        inputBox.addEventListener('input', shake(() => {
            console.log('发送搜索框');
        }))

也就是说,我先声明一个空的定时器,然后每次执行的时候,先判断定时器有没有,如果有,就进入清理定时器那一步,如果没有,就进行下一步,所以,我们看浏览器怎么返回

虽然我执行了很多次,打了好几个1,但是,只给我返回一次

所以,以上就是实现防抖的重要技术要点了

🤞作者小三是刚刚毕业不久全栈工程师,写的技术文章基本上是学习过程中笔记整理而来,大家看了之后如果喜欢可以给小弟点点赞哦。
🎁 粉丝福利:学习资料、简历模板统统都有点击领取