2022-01-01【技术】一篇让你彻底明白防抖和节流以及应用场景

1.谈一谈防抖与节流?有什么区别?如何实现?
定义

所谓防抖,就是指触发事件后,在 n 秒后函数才会执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
所谓节流,就是指连续触发事件,但是在 n 秒中只执行一次函数。

区别

函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数。

使用场景

防抖:
1、搜索框搜索输入。只需用户最后一次输入完,再发送请求。
2、手机号、邮箱验证输入检测。
3、窗口大小Resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。

节流:
1、滚动加载,加载更多或滚到底部监听。
2、谷歌搜索框,搜索联想功能。
3、高频点击提交,表单重复提交。

2.防抖的使用 例:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>防抖与节流</title>
    <style>
        .box {
            width: 200px;
            height: 200px;
            overflow: auto;
        }
    </style>
</head>
<body>
    <div class="box" id="container">
        <p>防抖演示</p>
        <p>防抖演示</p>
        <p>防抖演示</p>
        <p>防抖演示</p>
        <p>防抖演示</p>
        <p>防抖演示</p>
        <p>防抖演示</p>
        <p>防抖演示</p>
        <p>防抖演示</p>
    </div>
</body>
<script type="text/javascript">
    // 当连续触发scroll事件,handle函数只会在1秒时间内执行一次,在如果继续滚动执行,就会清除定时器,重新计时。相当于就是多次执行,只执行一次。
    function debounce(fn, wait) {
        var timeout = null;// 使用闭包,缓存变量
        return function () {
            if (timeout !== null) {
                console.log('清除定时器啦')
                clearTimeout(timeout); //清除这个定时器
            }
            timeout = setTimeout(fn, wait);
        }
    }
    // 处理函数
    function handle() {
        console.log(Math.random());
    }
    var container = document.getElementById('container')
    container.addEventListener('scroll', debounce(handle, 1000));
</script>
</html>

3.节流的使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>防抖函数</title>
    <style>
        .box {
            width: 200px;
            height: 200px;
            overflow: auto;
        }
    </style>
</head>
<body>
    <div class="box" id="container">
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
        <p>节流演示</p>
    </div>
</body>
<script>
    // 在前端开发中会遇到一些频繁的事件触发,比如: 1000/200= 5ms;
    // window 的 resize(窗口大小)、scroll(滚动)
    // mousedown、mousemove
    // keyup、keydown
    // ……
    // 前端开发中,我们常常会去监听滚动事件或者用户输入框验证事件,如果事件处理没有频率限制,就会加重浏览器的负担,影响用户的体验感,
    // 因此,我们可以采取防抖(debounce)和节流(throttle)来处理,减少调用事件的频率,达到较好的用户体验。
    // throttle 节流 指定时间间隔内只会执行一次任务;
    // 节流的原理很简单: 如果你持续触发事件,每隔一段时间,只执行一次事件。
    // 关于节流的实现,有两种主流的实现方式,一种是使用时间戳,一种是设置定时器。
    // 场景很多,常见的有:
    // 屏幕尺寸变化时页面内容的变动,执行相应逻辑;
    // 监听鼠标滚动时间,执行相应逻辑;
    // 监听重复点击时的时间,执行相应逻辑
    // 规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效。
    // 在节流函数内部使用开始时间prev、当前时间now和剩余时间remain,当剩余时间小于等于0意味着执行处理函数,这样保证第一次就能立即执行函数并且每隔delay时间执行一次;
    function throttle(func, delay) {
        var timer = null; // 使用闭包,缓存变量
        var prev = Date.now(); // 最开始进入滚动的时间
        return function () {
            var context = this; // this指向window
            var args = arguments;
            var now = Date.now();
            var remain = delay - (now - prev); // 剩余时间
            clearTimeout(timer);
            // 如果剩余时间小于0,就立刻执行
            if (remain <= 0) {
                func.apply(context, args);
                prev = Date.now();
            } else {
                timer = setTimeout(func, remain);
            }
        }
    }
    // 处理的函数
    function handle() {
        console.log(Math.random());
    }
    var container = document.getElementById("container");
    container.addEventListener("scroll", throttle(handle, 3000))//20次 真实需求中 一秒调依次函数就足够了 怎么办?
</script>
</html>

拓展:

js防抖与节流以及应用场景

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

防抖
防抖的原理就是:要等你触发完事件 n 秒内不再触发事件,我才执行。

 //debounce 
    function debounce(func, wait) {
        var timeout;
        return function () {
            var context = this;
            var args = arguments;
            clearTimeout(timeout);
            timeout = setTimeout(function () {
                func.apply(context, args)
            }, wait);
        }
    }

节流
节流的原理很简单:如果你持续触发事件,每隔一段时间,只执行一次事件。
有两种主流的实现方式,一种是使用时间戳,一种是设置定时器。

(1)时间戳实现
特点:第一次事件会立刻执行,停止触发后没有办法再执行事件。

function throttle(func, wait) {
        var previous = 0;
        return function () {
            var now = Date.now();
            var context = this;
            var args = arguments;
            if (now - previous > wait) {
                func.apply(context, args);
                previous = now;
            }
        }
    }

(2)定时器实现
特点:会在 n 秒后第一次执行,事件停止触发后依然会再执行一次事件。

function throttle(func, wait) {
        var timeout;
        return function () {
            var context = this;
            var args = arguments;
            if (!timeout) {
                timeout = setTimeout(function () {
                    func.apply(context, args);
                    timeout = null;
                }, wait)
            }
        }
    }

应用场景:
防抖:
1.浏览器窗口 缩放,resize事件,常见于需要做页面适配的时候,需要 根据最终呈现的页面情况进行dom渲染。
2.表单的按钮提交事件,例如登录,发短信,避免用户点击太快,以至于发送了多次请求。
3.search搜索框输入,只需用户最后一次输入完在发送请求。
4.文本编辑器实时保存,当无任何更改操作1s后进行保存。

节流:
1.鼠标不断点击触发,mousedown(单位时间内只触发一次) mousemove事件。
2.商品预览图的放大镜效果。
3.谷歌搜索框(支持实时搜索),搜索联想功能。
4.scroll事件,每隔1s计算一次位置信息。

窗外
雨落纷纷
宿雾空

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容