js的防抖与节流

应用场景:开发中多会出现监听页面滚动事件的函数,比如监听页面滚动高度来判断是否显示“回到顶部”的按钮以及keyup事件等

函数防抖:

定义:多次触发事件,事件函数只处理一次,并且是在触发操作结束的时候触发

原理:对处理函数进行延时操作,如果在设定的延时到来之前,函数被再次触发,则清除上一次的延时操作定时器,重新定时。

原理图:

js的防抖与节流_第1张图片

// window.onScroll的触发实例
let timer;
window.onScroll = function () {
    if (timer) {
        clearTimeout(timer);
    }
    timer = setTimeout(() => {
        // 滚动条的位置
        let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
        console.log('滚动条位置:' + scrollTop);
        timer = false;
    }, 500)
}

效果如下:

js的防抖与节流_第2张图片

防抖函数的封装:

/**
 * 防抖函数
 * @param method 事件触发的操作
 * @param delay 多少毫秒内连续触发事件,不会执行
 * @returns {Function}
 */
function debounce(method, delay) {
    let timer = null;
    return () => {
        let self = this;
        let args = arguments;
        timer && clearTimeout(timer);
        timer = setTimeout(() => {
            method.apply(self, args);              
        }, delay);         
    }
}
window.onScroll = debounce(() => {
    let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
    console.log('滚动条位置:' + scrollTop);
})

函数节流

定义:触发函数事件之后,只能在规定的时间之后才能再次触发该函数

原理图:

js的防抖与节流_第3张图片

函数节流主要有两种方式:时间戳和定时器

时间戳形式的代码:

let throttle = (func, delay) => {
    let prev = Date.now();
    return () => {
        let context = this;
        let args = arguments;
        let now = Date.now();
        if(now - prev >= delay) {
            func.apply(context, args);
            prev = Date.now();
        }
    }
}
function handle() {
    console.log(Math.random());
}
window.addEventListener('scroll', throttle(handle, 1000));

定时器形式的代码:

let throttle = (func, delay) => {
    let timer = null;
    return () => {
        let context = this;
        let args = arguments;
        if (!timer) {
            timer = setTimeout(() => {
                func.apply(context, args);
                timer = null;
            },delay)
        }
    }
}
let handle = () => {console.log(Math.random())};

window.addEventListener('scroll', throttle(handle, 1000));

更精确点可以用时间戳+定时器:

var throttle = (func, delay) => {
    let timer = null;
    let startTime = Date.now();
    return () => {
        let curTime = Date.now();
        let remaining = delay - (curTime - startTime);
        let context = this;
        let args = arguments;
        if (remaining > 0) {
            func.apply(context, args);
            startTime = Date.now();
        } else {
            timer = setTimeout(func, remaining);
        }
    }
}
function handle () {console.log(Math.random())};
window.addEventListener('scroll', throttle(handle, 1000));

总结:

函数防抖:将几次操作合并为一此操作进行。原理是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置。这样一来,只有最后一次操作能被触发。

函数节流:使得一定时间内只触发一次函数。原理是通过判断是否到达一定时间来触发函数。

区别: 函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数。 比如在页面的无限加载场景下,我们需要用户在滚动页面时,每隔一段时间发一次 Ajax 请求,而不是在用户停下滚动页面操作时才去请求数据。这样的场景,就适合用节流技术来实现。

 

 

 

 

 

 

 

 

你可能感兴趣的:(学习笔记)