事件的节流与防抖

160 阅读4分钟

原地址:juejin.cn/post/684490…

1. 节流(throttle)

why

例如当我们需要检测页面滚动来执行回调函数的时候,若我们不进行任何处理,则会造成很大的性能消耗。

how

实现一个方法,让回调函数在一段时间内只执行一次。

<button id="btn" onclick="better_scroll()">按钮</button>
// fn是我们需要包装的事件回调, interval是时间间隔的阈值
function throttle(fn, interval{
    // last为上一次触发回调的时间
    let last = 0
    // 将throttle处理结果当作函数返回
    return function ({
        // 保留调用时的this上下文
        let context = this
        // 保留调用时传入的参数
        let args = arguments
        // 记录本次触发回调的时间
        let now = +new Date()
        // 判断上次触发的时间和本次触发的时间差是否小于时间间隔的阈值
        if (now - last >= interval) {
            // 如果时间间隔大于我们设定的时间间隔阈值,则执行回调
            last = now;
            fn.apply(context, args);
        }
    }
}
// 用throttle来包装点击的回调
const better_scroll = throttle(() => console.log('触发了点击事件'), 1000)

效果展示:在一秒之内方法最多只能调用一次

2. 防抖(debounce)

why

这里以用户注册时验证用户名是否被占用为例,如今很多网站为了提高用户体验,不会再输入框失去焦点的时候再去判断用户名是否被占用,而是在输入的时候就在判断这个用户名是否已被注册,这样的做法不好的是当用户输入每一个字符,都会进行请求判断,不仅对服务器的压力增大了,对用户体验也未必比原来的好。而理想的做法应该是这样的,当用户输入第一个字符后的一段时间内如果还有字符输入的话,那就暂时不去请求判断用户名是否被占用。解决这个问题的方法叫做防抖。

how

设置一个一秒的延时器,当用户在一秒内再次输入时,将延时器重置,直到用户一秒内不再输入数据,这时再去请求。

先用按钮演示:

<button id="btn" onclick="better_scroll()">按钮</button>
// fn是我们需要包装的事件回调, delay是每次推迟执行的等待时间
function debounce(fn, delay{
    // 定时器
    let timer = null
    // 将debounce处理结果当作函数返回
    return function ({
        // 保留调用时的this上下文
        let context = this
        // 保留调用时传入的参数
        let args = arguments
        // 每次事件被触发时,都去清除之前的旧定时器
        if (timer) {
            console.log("重置定时器")
            clearTimeout(timer)
        }
        // 设立新定时器
        timer = setTimeout(function ({
            fn.apply(context, args)
        }, delay)
    }
}
// 用debounce来包装点击的回调
const better_scroll = debounce(() => console.warn('触发了滚动事件'), 1000)

稍作修改用于校验用户名是否重复

<input type="text" oninput="better_scroll()">

效果展示: