首页 > 其他 > 详细

防抖和节流

时间:2021-01-21 09:25:33      阅读:33      评论:0      收藏:0      [点我收藏+]

防抖和节流

防抖

  • 不管事件触发频率多高,一定在事件触发 n 秒后才执行,如果在一个事件执行的 n秒内又触发了这个事件,就以新的事件的时间为准
/**
 * 防抖:不管事件触发频率多高,一定在事件触发 n 秒后才执行,如果在一个事件执行的 n秒内又触发了这个事件,就以新的事件的时间为准
 * @callback fn  -被调用的函数 
 * @param {number} [wait = 300] -定时器时间  
 * @param {boolean} [immediate = false] -是否要立即执行一次  
 */
export function debounce(fn, wait = 300, immediate = false) {

    // 参数验证
    if (typeof fn != ‘function‘)
        throw Error("第一个参数必须是函数!");
    if (typeof wait != ‘number‘)
        throw Error("第二个参数必须是数字!");
    if (typeof immediate != ‘boolean‘)
        throw Error("第三个参数必须是布尔值!");

    let timer = null;

    // 返回一个函数
    return function() {

        // 是否要立即执行一次
        if (!timer && immediate)
            fn.apply(this, arguments);

        // 每次触发事件时都取消之前的定时器
        clearTimeout(timer);

        // setTimeout 中使用箭头函数,就是让 this指向 返回的该闭包函数,而不是 debounce函数 的调用者
        timer = setTimeout(() => {
            fn.apply(this, arguments)
        }, wait)
    }
}

函数不能使用箭头函数,否则 this 执行会有问题

js使用

window.addEventListener(‘resize‘, debounce(function() {}, 200));

vue使用

mehtod: debounce(function() {}, 200)

节流

  • 不管事件触发频率有多高,只在单位时间内执行一次。

使用时间戳

第一次事件肯定触发,最后一次不会触发(比如说监听 onmousemove,则鼠标停止移动时,立即停止触发事件)

function throttle(fn, wait)  {
    // 记录上一次执行的时间戳
    let previous = 0;
    return function(...args) {
        // 当前的时间戳,然后减去之前的时间戳,大于设置的时间间隔,就执行函数,否则不执行
        if(Date.now() - previous > wait) {
            // 更新上一次的时间戳为当前时间戳
            previous = Date.now();
            fn.apply(this, args);
        }
    }
}

使用定时器

第一次事件不会触发(fn是放在 setTimeout中执行的,所以第一次触发事件至少等待 wait 毫秒之后才执行),最后一次一定触发

function throttle(fn, wait)  {
    // 设置一个定时器
    let timer = null;
    return function(...args) {
        // 判断如果定时器不存在就执行,存在则不执行
        if(!timer) {
            // 设置下一个定时器
            timer = setTimeout(() => {
                // 然后执行函数,清空定时器
                timer = null;
                fn.apply(this, args)
            }, wait)
        }
    }
}

定时器和时间戳结合

两者结合可以实现,第一次事件会触发,最后一次事件也会触发

/**
 * 节流: 不管事件触发频率有多高,只在单位时间内执行一次
 * 第一次事件和最后一次事件都触发
 * @callback fn  -被调用的函数 
 * @param {number} [wait = 300] -定时器时间  
 */

export function throttle(fn, wait = 300) {

    // 参数验证
    if (typeof fn != ‘function‘)
        throw Error("第一个参数必须是函数!");
    if (typeof wait != ‘number‘)
        throw Error("第二个参数必须是数字!");

    // 设置一个定时器
    let timer = null;

    // 记录上一次执行的时间戳
    let previous = 0;

    return function() {
        // 当前的时间戳,然后减去之前的时间戳,大于设置的时间间隔
        if (Date.now() - previous > wait) {
            clearTimeout(timer)
            timer = null;

            // 更新上一次的时间戳为当前时间戳
            previous = Date.now();

            fn.apply(this, arguments);
        } else if (!timer) {

            // 设置下一个定时器
            timer = setTimeout(() => {
                timer = null;
                fn.apply(this, arguments);
            }, wait)
        }
    }
}

使用方法和防抖一样

防抖和节流

原文:https://www.cnblogs.com/landuo629/p/14305945.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!