JS-防抖和节流

392 阅读3分钟

今天遇到一个笔试题,就是有关节流的,今天梳理了一下防抖和节流。

问题1: 如果实现了dom拖拽功能,但是在绑定拖拽事件的时候发现每当元素稍微移动一点便触发了大量的回调函数,导致浏览器直接卡死,这个时候怎么办?

问题2:如果给一个按钮绑定了表单提交的post事件,但是用户有些时候在网络情况极差的情况下多次点击按钮造成表单重复提交,如何防止多次提交的发生?

1、定义

函数防抖(debounce)

当调用动作过 n 毫秒后,才会执行该动作,若在这 n 毫秒内又调用此动作则将重新计算执行时间。

函数节流(throttle)

规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效

2、作用

解决高频繁问题,既能节省浏览器CPU资源,又能让页面浏览更加顺畅,不会因为js的执行而发生卡顿。

3、二者的区别

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

4、使用场景

防抖

  • search搜索,用户在不断输入值时(keyup,keydown),用防抖来节约请求资源。
  • 拖拽、鼠标移动(mousemove)事件
  • window触发resize的时候,不断的调整浏览器窗口大小,会不断的触发这个事件,用防抖来让其只触发一次

节流

  • 鼠标不断点击触发,mousedown(单位时间内只触发一次)
  • 监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断

5、实现

界面实现代码:

<div id='debounce' >
    <h3>这是防抖函数的例子</h3>
    <p>在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。</p>
    <div style="padding:10px">
          <strong>示例1:</strong>
          <input id="debounceInput" type="text">
    </div>

    <div style="padding:10px">
           <strong>示例2:</strong>
           <div id="debounceCount"></div>
    </div>
 </div>

 <div id='throttle'>
   <h3>这是节流函数的例子</h3>
   <p>规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效。</p>
   <button id='but' @click='throttleClick'>点击一下</button>
</div>

防抖js代码:

var fd = document.getElementById('debounceInput');
var fdDivCount = document.getElementById('debounceCount');
var count = 1;
function outPut() {
    console.log('输出,', fd.value); 
}

function addWhenMove() {
    fdDivCount.innerHTML=count++;
}

// 防抖函数
function _debounce(fun,delayTime) {
    var delayTime = delayTime || 500;
    var timer;
    return function () {
        var that =this;
        var args = arguments;
        if(timer){
            clearTimeout(timer);
        }
        timer = setTimeout(() => {
            fun.apply(that,args)
        }, delayTime);
    }
}
fd.addEventListener('keyup', _debounce(outPut, 1000))
fdDivCount.onmousemove = _debounce(addWhenMove, 1000,true)

运行效果:

示例1: image

示例2: image

节流js代码:

new Vue({
       el:'#throttle',
       data:{},
       methods:{
         throttleClick:function (){
            let that = this
            let now = +new Date();
            if (lastTime && lastTime - now < 1000) {
               clearTimeout(timer);
            }
            timer = setTimeout(() => {
               console.log('点击一下');
               lastTime = +new Date()
            }, 1000);
          }
        }
})

运行效果: image

题目描述:

现有一个文本输入框(<input type="text" id="search"/>),当用户输入时,500ms输出(console)一次输入框的值,请编写单独的节流函数throttle,并且实现该功能。 例如:throttle(fn , gapTime)

参考链接:juejin.im/post/684490…