什么是防抖和节流?有什么区别?如何实现?

在前端开发中会遇到一些频繁的事件触发,例如input,keyup,keydown,scroll,resize,mousemove等,这非常影响性能,所以我们需要控制它们触发的频率,方法就是防抖与节流。

函数防抖(debounce)

定义:当持续触发事件时(如连续点击按钮多次),一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,有一次触发了事件,就重新开始延时。

防抖:按照固定的频率执行,比如 3 秒执行一次Input事件,如果再3秒前之前就触发Input,那么我们清除计时器,从刚刚Input的时候再次计时,再3秒后触发;

原理:维护一个计时器,规定在延时时间后触发函数,但是在延时时间内再次被触发的话,就取消之前的计时器而重新设置,这样就能够保证只有最后一次操作被触发。即将所有操作合并为一个操作进行,并且只有最后一次操作是有效操作。

应用场景:在项目中,我有一个需要实时搜索并出结果的操作,简单的说,就是在一个input上绑定了keyup事件,在执行keyup时在里面设置一个定时器,因为一般输入比时间要快,前面的keyup里面的事件就被clear,然后再接着执行后面的搜索。也就实现了简单的防抖操作

函数节流(throttle)

定义:按照设定的固定时间执行一次函数,比如200ms一次。注意:固定就是你在mousemove过程中,执行这个节流函数,它一定是200ms(你设定的定时器延迟时间)内执行一次。没到200ms,一定会返回,不会执行回调函数的。

节流:按照固定的时间执行,没到时间,则不执行,到时间才执行,通过一个开关来控制。

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

函数防抖代码实现:

触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间
每次触发事件时都取消之前的延时调用方法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>防抖</title>
</head>
<body>
<input type="text" id="txt_id">
<script>
    function debounce(fn) {
       let timer = null
       console.log(this)
       return function () {
           clearTimeout(timer)
           console.log('aaa',this)
           timer = setTimeout(()=>{
               console.log('bb',this)
                fn.call(this)
           }, 2000)

       }
    }
    function say () {
        console.log('hello word')
    }
    Oinput = document.getElementById('txt_id')
    Oinput.addEventListener('input', debounce(say))
</script>

</body>
</html>

函数节流代码实现:

高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率

每次触发事件时都判断当前是否有等待执行的延时函数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>节流</title>
    <style>
        h1 {
            background: skyblue;
        }
    </style>
</head>
<body>
<h1 id="h1_id">0</h1>
<script>
    function say(e) {
        let ev = e || event
        ev.target.innerText = count++
    }
    function throttle(fn) {
        console.log(fn)
        let canRun = true
        return function () {
            if (!canRun)
                return
            canRun = false
            setTimeout(() => {
                fn.apply(this, arguments)
                canRun = true
            }, 100)
        }
    }
    let count = 0
    oH1 = document.getElementById('h1_id')
    oH1.addEventListener('mousemove', throttle(say))
</script>
</body>
</html>

参考链接:http://www.52codes.net/develop/javascript/59224.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>debounce</title>
    <style>
        #main {
            width: 300px;
            height: 300px;
            background-color: #ccc;
        }
    </style>
</head>
<body>
    <div id="main"></div>
</body>
<script>

    // function debounce(fn) {
    //     let timer = null;
    //     return function() {
    //         clearTimeout(timer);
    //         timer = setTimeout(() => {
    //             fn();
    //         }, 1000)
    //     }
    // }

    // function throttle(fn) {
    //     let canRun = true;
    //     console.log(11)
    //     return function() {
    //         if (!canRun) {
    //             return false;
    //         }
    //         canRun = false;
    //         setTimeout(() => {
    //             fn();
    //             canRun = true;
    //         }, 1000)
    //     }
    // }
    // function position() {
	//     console.log(1);
    // }
    // const area = document.getElementById('main');
    // area.addEventListener('mousemove', position);
// area.addEventListener('mousemove', debounce(position));
// area.addEventListener('mousemove', throttle(position));


const div = document.querySelector('#main');
// 防抖:按照一定频率进行,和时间轴无关
const debounce = (fn) => {
    let timer;
    return function() {
        clearTimeout(timer); // 你一动,我就给你取消掉
        timer = setTimeout(() => {
            fn();
        }, 1000);
    }
}
// 节流:按照某一时间频率运行
const throttle = (fn) => {
    let canRun = true;
    return function() {
        if (!canRun) {
            return false;
        }
        canRun = false;
        setTimeout(() => {
            fn();
            canRun = true;            
        }, 1000);
    }
} 
const move = () => {
	console.log('11')
}
div.addEventListener('mousemove', throttle(move));
</script>
</html>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

. . . . .

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值