JS--函数防抖问题

防抖的需求

我们要解决防抖的问题,第一步要先了解防抖是什么,为什么会产生抖动;
在日常生活中我们经常会需要在表格中输入内容,点击滑块完成验证,scroll事件滚动事件,按钮提交,试想一下如果当我们每一次抬起鼠标向后台发送一次请求,或者移动滑块一次验证一次是不是耗时太久,scroll事件滚动如果碰一下就变化,容易抖动,那么防抖就是为了就是为了解决这个事情

防抖的概念

我们要解决防抖的问题,那么首先要了解防抖的概念

防抖:事件响应函数在一段时间后才执行,如果在这段时间内在次调用,则重新计算执行时间,当预定的时间内没有再次调用该函数,则执行事件响应函数。( 好像当一件事执行后,等待相应时间后才能看到结果,但是如果中途等不及将这件事重新做了一次,又要等待相同的是、时间才能看到结果))

怎么解决防抖

先上一个html和css,方便后续的引入

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .wrapper {
            background-color: #444;
            height: 200px;
            line-height: 200px;
            /* 加入margin方便观察效果 */
            margin-left: 80px;
            width: 30%;
            color: #fff;
            text-align: center;
        }
    </style>
</head>

<body>
    <div class="wrapper"></div>
</body>

</html>

这就是一个简单的布局,这里不再做解释.
再给他加一个移动事件以便后期使用

//获取当前的div
        let wrapper = document.querySelector('.wrapper');
        // 计数
        let count = 0;
        // 事件
        function dosomeThing(e) {
       		// console.log(e)
             console.log(this)
            wrapper.innerHTML = count++;
        }
       wrapper.onmousemove = dosomeThing 

控制时间

如果看清了上面的概念,那么我们第一个要解决的问题就是时间的问题,我们要控制在多长时间后再一次触发这件事件,怎么做呢?

function debounce1(func, wait) {
    let timer;
    return function() {
        console.log(this)
        clearTimeout(timer); //进来先清除定时器
        timer = setTimeout(func, wait)
    }
}
//将点击事件引用我们的防抖函数
 wrapper.onmousemove = debounce1(dosomeThing, 500)

此时当我们在移入的时候,我们会发现如果不停移动就不会输出,只有停下500ms后才会触发,如下图
在这里插入图片描述
我们可以发现下面我们移动了这么多次上面的数据也只加了一,当然这样也就不难发现我们上面打印的this值得问题,所有有了我们的第二步;

改变this指向

你们可能看的不太明显,最后一个打印window的是我们的dosomeThing,上面的div打印来自于debounce1的返回值的第一行,我们肯定希望我们的事件响应函数指向我们的目标元素,那么我们怎么实现呢:

function debounce1(func, wait) {
    let timer;
    return function() {
        // console.log(this)
        // 改变执行函数内部this指向问题
        // 因为这里的this指向我们的事件源,所以在这里保存this
        let that = this;
        clearTimeout(timer); //进来先清除定时器
        timer = setTimeout(function() {
            // 用call方法改变this指向,这里用apply也能达到同样的效果,两者的区别在于传参方式的不同,一个call传入参数列表,apply传入参数数组
            func.call(that)
        }, wait)
    }

这个时候让我们看看控制台的输出结果
在这里插入图片描述
这个时候执行函数的this指向问题已经解决,那么我们这里放开我们的console.log(e)看一下结果;
1
这里输出underfined,我们的MouseEvent消失了,那么下面我们来解决这个问题;

修复MouseEvent

我们可以发现在return内部打印arguments返回的对象有鼠标事件,那么我们在下面将他加进去,保存鼠标事件;

function debounce1(func, wait) {
    let timer;
    return function() {
        // arguments 是一个对应于传递给函数的参数的类数组对象。
        console.log(arguments)
            // console.log(this)
            // 改变执行函数内部this指向问题
            // 因为这里的this指向我们的事件源,所以在这里保存this
        let that = this;
        let argus = arguments;
        clearTimeout(timer); //进来先清除定时器
        timer = setTimeout(function() {
            // 用spply方法改变this指向,这里用call也能达到同样的效果,两者的区别在于传参方式的不同,一个call传入参数列表,apply传入参数数组
            //    arguments 是一个对应于传递给函数的参数的类数组对象,这里将argus传入,保存event
            func.apply(that, argus)
        }, wait)
    }

这时我们再看一下执行函数的console.log(e)
1
正常
那么到这里基本就已经完成了,封装后续使用,欢迎取用

/**
 * 防抖函数
 * @param {Function} func 执行的响应函数
 * @param {Number} wait 等待时间
 */
function debounce1(func, wait) {
    let timer;
    return function() {
        let that = this;
        let argus = arguments;
        clearTimeout(timer);
        timer = setTimeout(function() {
            func.apply(that, argus)
        }, wait)
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值