likes
comments
collection
share

你真的分得清“防抖”与“节流”吗

作者站长头像
站长
· 阅读数 30

昨天看到朋友在看防抖节流的相关知识点,我就问了问他防抖跟节流有什么区别,他回:防抖不就是为了节流吗?好好好,看来必须好好调教一下了。我说防抖跟节流是肩并肩的,同一类东西,他一脸疑惑,然后我就开始一顿输出...

前言

防抖节流确实容易混淆,因为我们平常也总是把这两个连在一起说。但其实防抖就是防抖,节流就是节流,它们都属于优化技术的一种,一定不能把节流当作防抖的作用了。此文将带你彻底分清并理解防抖与节流。

防抖与节流

共同点:

都是用来避免一个事件短时间内被重复触发多次,减少函数的调用频率,以减少不必要的操作从而提高性能。通常在用户输入(input)、窗口大小调整(resize)、滚动事件(scroll)中使用,这些都是触发非常频繁的事件。input绑定的大多是keyup事件,也就是每松开一个键位它都会触发一次。而scroll更是离谱,随便滚动一下滑轮就触发了几十次甚至上百次。

差别:

先讲节流,以方便我们更好地理解防抖

节流

简单来说就是每过一段时间就执行一次。举个例子,你在导航上位置的变化。把计算你移动的距离当作一个高频事件,一秒计算一千次,你每踏一步这个事件就触发了几百次,显然这造成了不必要的计算负担。节流技术就是可以利用定时器让这个事件在一定的时间间隔内最多执行一次,比如每秒执行一次,那么我们就减少了大量的计算,从而也不太影响你获取在导航上位置的变化。

防抖

顾名思义,防止抖动。还是举上面的这个导航的例子,如果我们跑的够快,那么根据上面节流后的情况,我们是不是在导航上就是跳跃性的,就像位置在抖动。那么防抖技术就是在你停止跑动且过了一小段时间时,才会计算一次你移动的距离,比如你停下来过了一秒就计算一次,那么我们是不是就防止了我们在跑步时导航上位置的抖动,所以叫做防抖。

代码实现方法

看完上面的阐述,想必我们对防抖与节流已经有了大概的了解,那我们现在来聊聊实现方法,这里我用了input中的keyup事件来做例子

节流

下面是JavaScript实现代码,其中inputa是普通input的id,inputc是节流input的id

const inputa = document.getElementById("inputa")
const inputc = document.getElementById("inputc")

const ajax = (content) => {
    console.log(`ajax request ${content}`);
}
const throttle = (func, delay) => {
    // last:上一次是什么时候执行的
    // deferTimer 定时器id
    let last, deferTimer
    // 事件的处理函数
    // 定义时,生成时 func,delay
    // keyup return func 调用时能找到闭包的自由变量
    return (args) => {
        let now = +new Date()
        if (last && now < last + delay) {
            // 触发干掉
            clearTimeout(deferTimer)
            deferTimer = setTimeout(() => {
                last = now
                func(args)
            }, delay)
        } else {
            last = now
            func(args)
        }
    }
}

inputa.addEventListener("keyup", (e) => {
    ajax(e.target.value)
})
let throttledFunc = throttle(ajax, 1000)

inputc.addEventListener("keyup", (e) => {
    let value = e.target.value
    throttledFunc(value)
})
  • 功能介绍:简单的节流实现,在控制台输出在输入框输入的值,每一秒输出一次。
  • 关键:其中节流的重点就在throttle方法,利用了闭包的思想return出一个方法。通过let now = +new Date()获取当前时间,last代表上一次事件执行的时间,delay代表每多少时间执行一次,if语句中的作用就是在最后一次行为结束时也会运行一次且清除定时器,else则是让每段时间都会运行一次。

防抖

防抖较节流会更容易实现些,下面是JavaScript实现代码,其中unDebounce是普通input的id,debounce是防抖input的id

const inputun = document.getElementById('unDebounce')
const inputis = document.getElementById('debounce')
function handleNameSearch(e) {
    const value = e.target.value
    fetch('http://localhost:3000/users')
        .then(res => res.json())
        .then(data => {
            const users = data
            // 数组上es6的新方法, filter 过滤
            const filterUsers = users.filter(user => {
                // 字符串中新方法
                return user.name.includes(value)
            })
            console.log(filterUsers);
        })
}
// 闭包
function debounce(func, delay) {
    // 返回值必须得是函数 keyup 事件处理函数
    return function (args) {
        clearTimeout(func.id)
        // 函数是对象   id挂在func上  func是闭包中的自由变量
        func.id = setTimeout(() => {
            func(args)
        }, delay);
    }
}
inputun.addEventListener('keyup', handleNameSearch)
const debounceNameSearch = debounce(handleNameSearch, 500)
inputis.addEventListener('keyup', debounceNameSearch)
  • 功能介绍:这是一个input搜索数据库中姓名的方法,也就是在搜索姓名时停止输入0.5秒后才会进行搜索,而不是每松开一个键位就搜索一次。
  • 关键:其中防抖的重点就在debounce方法,现在我们来剖析一下其中代码的含义。这里我们用到的是闭包思想,return出去了一个方法。clearTimeout用来消除上一次操作的定时器,也就是你在0.5秒内进行了一次新的操作就将上一次操作形成的定时器消除,直到你在一次操作后的0.5秒未进行任何操作了就执行搜索操作。

结语

清楚了防抖与节流的原理后,我们就大致可以明白在各种场景中根据具体的业务需求该如何选择。性能提升对于我们程序员是一门很深的学问,它为我们带来优质的运行效率,大幅提升用户体验。

转载自:https://juejin.cn/post/7386916905008349199
评论
请登录