手写防抖节流

手写防抖节流文章目录手写前端常用技巧 防抖节流防抖节流 1 首节流 2 尾节流 3 首尾节流总结手写前端常用技巧 防抖节流防抖 当持续触发事件时 一定时间内没有再触发事件 才会在一段时间之后触发事件处理函数 节流 当持续触发事件时 保证一段 delay 之内 只调用一次函数防抖源代码 DOCTYPE tml htmllang en head metacharset UTF 8 metacharset UTF 8 head htmllang en


手写前端常用技巧-防抖节流

防抖

  • 源代码
 
     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>防抖 
       title>  
        head> <body> <label for='undebounce'>没防抖: 
         label> <input type="text" id='undebounce' onInput='onInput1(event)' > <br /> <label for="debounce">有防抖: 
          label> <input type="text" id='debounce' onInput='debounceInput(event)' > <script> function debounce(fn, delay){ 
            let time = null return function(...args){ 
            if(time){ 
            clearTimeout(time) } time = setTimeout(()=>{ 
            fn.apply(this, args) },delay) } } function onInput(e){ 
            val = e.target.value if(val){ 
            console.log('有防抖',val) } } const debounceInput = debounce(onInput, 300) function onInput1(e){ 
            val = e.target.value if(val){ 
            console.log('没有防抖',val) } }  
           script>  
            body>  
             html> 
  • 执行结果

请添加图片描述

::: tip

  • 结果分析
  1. 没有防抖的输入框持续输入时,每键入一个字母都执行一次处理函数
  2. 有防抖的输入框持续输入时,在键入字母结束之后才执行一次处理函数

:::

节流

1. 首节流

首节流,时间戳的实现,首次触发立即执行,停止触发后,没办法再次执行

  • 源代码
 
     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>节流throttle 
       title>  
        head> <body> <ul> <li>1 
         li> <li>2 
          li> <li>3 
           li> <li>4 
            li> <li>5 
             li> <li>6 
              li> <li>7 
               li> <li>8 
                li> <li>9 
                 li> <li>1 
                  li> <li>2 
                   li> <li>3 
                    li> <li>4 
                     li> <li>5 
                      li> <li>6 
                       li> <li>7 
                        li> <li>8 
                         li> <li>9 
                          li>  
                           ul>  
                            body> <style> body{ 
                              display: flex; justify-content: center; } ul, li { 
                              padding:0; margin: 0; } li{ 
                              width: 250px; height:200px; list-style: none; display: flex; justify-content: center; align-items: center; } li:nth-child(2n){ 
                              background:whitesmoke; } li:nth-child(2n+1){ 
                              background:yellow; }  
                             style> <script> // 首节流,时间戳的实现,停止触发后,没办法再次执行 function throttle(fn, interval){ 
                               let prev = 0; return function(...args){ 
                               const now = Date.now(); if( now-prev >= interval ){ 
                               prev = now fn.apply(this, args) } } } function handle(){ 
                               console.log(new Date()) } const throttleHandler = throttle(handle, 3000) console.log('tt', throttleHandler) window.addEventListener('scroll', throttleHandler)  
                              script>  
                               html> 

请添加图片描述

可以看到,只要滑动了,就会触发事件,但是停止滑动之后,不会触发最后一次。

2. 尾节流

定时器实现,不会立即执行,而是在delay之后执行

最后停止触发之后,还会执行一次

  • 源代码
 
     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>节流throttle 
       title>  
        head> <body> <ul> <li>1 
         li> <li>2 
          li> <li>3 
           li> <li>4 
            li> <li>5 
             li> <li>6 
              li> <li>7 
               li> <li>8 
                li> <li>9 
                 li> <li>1 
                  li> <li>2 
                   li> <li>3 
                    li> <li>4 
                     li> <li>5 
                      li> <li>6 
                       li> <li>7 
                        li> <li>8 
                         li> <li>9 
                          li>  
                           ul>  
                            body> <style> body{ 
                              display: flex; justify-content: center; } ul, li { 
                              padding:0; margin: 0; } li{ 
                              width: 250px; height:200px; list-style: none; display: flex; justify-content: center; align-items: center; } li:nth-child(2n){ 
                              background:whitesmoke; } li:nth-child(2n+1){ 
                              background:yellow; }  
                             style> <script> // 尾节流,定时器实现,不会立即执行,而是在delay之后执行 // 最后停止触发之后,还会执行一次 function throttle(fn,delay){ 
                               let timer = null return function(...args){ 
                               if( !timer ){ 
                               timer = setTimeout(()=>{ 
                               fn.apply(this, args) timer = null }, delay) } } } function handle(){ 
                               console.log(new Date()) } const throttleHandler = throttle(handle, 3000) console.log('tt', throttleHandler) window.addEventListener('scroll', throttleHandler)  
                              script>  
                               html> 

请添加图片描述

可以看到我们停止滑动之后还是触发了事件

3. 首尾节流

  • 源代码
 
     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>节流throttle 
       title>  
        head> <body> <ul> <li>1 
         li> <li>2 
          li> <li>3 
           li> <li>4 
            li> <li>5 
             li> <li>6 
              li> <li>7 
               li> <li>8 
                li> <li>9 
                 li> <li>1 
                  li> <li>2 
                   li> <li>3 
                    li> <li>4 
                     li> <li>5 
                      li> <li>6 
                       li> <li>7 
                        li> <li>8 
                         li> <li>9 
                          li>  
                           ul>  
                            body> <style> body{ 
                              display: flex; justify-content: center; } ul, li { 
                              padding:0; margin: 0; } li{ 
                              width: 250px; height:200px; list-style: none; display: flex; justify-content: center; align-items: center; } li:nth-child(2n){ 
                              background:whitesmoke; } li:nth-child(2n+1){ 
                              background:yellow; }  
                             style> <script> // 首尾节流,计时器+时间戳 function throttle(fn, delay){ 
                               let timer = null let startTime = 0 return function(...args){ 
                               let curTime = Date.now(); let remaining = delay - (curTime - startTime) // 清除旧的计时器 clearTimeout(timer) if(remaining <= 0 ){ 
                               fn.apply(this, args) startTime = Date.now() }else{ 
                               timer = setTimeout(()=>{ 
                               fn.apply(this, args) startTime = Date.now() }, remaining) } } } function handle(){ 
                               console.log(new Date()) } const throttleHandler = throttle(handle, 500) console.log('tt', throttleHandler) window.addEventListener('scroll', throttleHandler)  
                              script>  
                               html> 

请添加图片描述

在这里我们缩短节流时间,方便看效果。

可以看到每次滑动都至少触发两次事件,即首尾触发

总结

虽然防抖和节流都是避免同一时间频繁执行处理函数,但是原理却有一些差别

::: note

应用场景

  • 防抖 debounce
    • search搜索联想,用户在不断输入值时,用防抖来节约请求资源。
    • window触发resize的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用防抖来让其只触发一次
  • 节流 throttle
    • 鼠标不断点击触发,mousedown(单位时间内只触发一次)
    • 监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断

:::

文章详细信息,请查看个人博客

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/222685.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 下午3:12
下一篇 2026年3月17日 下午3:13


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号