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计算一次位置信息。

窗外
雨落纷纷
宿雾空

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容