js 防抖处理?

image.png

右下角有一个按钮来控制滑块位置, 具体代码如下

<style>
    #rollBtn .sc-box {
        bottom: 3rem;
        right: 3rem;
        background-color: rgba(var(--sc-primary-rgb), .5);
    }

    #rollBtn .sc-status-bottom {
        transform: rotate(180deg);
    }
</style>

<aside id="rollBtn">
    <div class="sc-box position-fixed d-inline-block rounded-circle cursor-pointer p-3 transition-500 waves-effect waves-dark">
        <img src="http://localhost:8002/assets/images/chevron-down.svg">
    </div>
</aside>

<script>
    function debounce(func, wait) {
        let timeout;
        return () => {
            clearTimeout(timeout);
            timeout = setTimeout(func, wait);
        }
    }

    $('#rollBtn .sc-box').click(() => {
        $("html").animate({
            scrollTop: 1000
        }, 1000);
    });
</script>

但是当用户连续点击的时候页面就会卡死, 这个情况可以怎么进行防抖优化?
debounce 是原先封装的方法, 但这个方法并不适用这个需求
debounce 是延迟执行, 也就是如果调这个方法传1秒, 那我点击这个按钮后1秒才开始执行里面的方法
想稍微改一下, 变成先执行, 后延迟1秒 (先执行$("html").animate, 并且在执行1期间将$("html").animate 锁定1秒的时间)

阅读 1.8k
5 个回答
✓ 已被采纳

送你一个可以立即执行的debounce函数

/**
 * @desc 函数防抖
 * @param func 目标函数
 * @param wait 延迟执行毫秒数
 * @param immediate true - 立即执行, false - 延迟执行
 */
function debounce (func, wait = 1000, immediate = true) {
    let timer;
    return function() {
        let context = this,
            args = arguments;
        if (timer) clearTimeout(timer);
        if (immediate) {
            let callNow = !timer;
            timer = setTimeout(() => {
                timer = null;
            }, wait);
            if (callNow) func.apply(context, args);
        } else {
            timer = setTimeout(() => {
                func.apply(context, args);
            }, wait)
        }
    }
}

jQuery的话,先使用 .stop() 结束动画,然后在执行动画就好了。

  • $("html").stop().animate({scrollTop: 1000}, 1000)

后来好像jQuery有改进过这个动画函数,但是我不记得了怎么改造了。只记得原来先 stop 然后再 animate 执行新动画这种步骤了。

防抖函数

const debounce = (fn, delay = 50) => {
    var timer
    return function () {
        var th = this
        var args = arguments
        if (timer) {
            clearTimeout(timer)
        }
        timer = setTimeout(function () {
            timer = null
            fn.apply(th, args)
        }, delay)
    }
}

这种问题可以使用节流,让用户点击后立马执行,设置节流时间为1s,用户在1s内的无论点击多少次只执行第一次就可以了。

function throttle(func, wait) {
    var context, args;
    var previous = 0;

    return function () {
        var now = +new Date();
        context = this;
        args = arguments;
        if (now - previous > wait) {
            func.apply(context, args);
            previous = now;
        }
    };
}
$("#rollBtn .sc-box").click(
    throttle(() => {
        $("html").animate(
            {
                scrollTop: 1000,
            },
            1000
        );
    }, 1000)
);
推荐问题
宣传栏