20190726-前端笔记-防抖和节流

防抖

为了避免一些监听事件为在自己预料的情况,频繁触发。or 在某些监听命令会频繁触发事件比如
resize
mousemove等等

未防抖 示例

       var count = 0,
          Elem = doc.getElementById('con')

        function appendCount(e) {
            console.log(e);
            
          Elem.innerHTML = count++
        }

        // 正常,没有防抖的情况下,直接监听执行
        Elem.addEventListener('mousemove', function() {
          appendCount()
        })

这会导致,只要鼠标移动,会导致Eelm.innerHTML不断改变。现在看起来好像没什么问题,如果是很多数据渲染或者请求几千条列表数据呢?

会导致浏览器不断回流和重绘。

那如何防抖呢??

触发mousemove时间后1s内,只有不在触发mousemove方法才会能执行appendCount()

var count = 0,
    Elem = doc.getElementById('con');
     
function debounce(fn, waitTime){
    // 定义定时器
     var timeoutFn = null;
     
     return function (){
          // 清空定时器
          clearTimeout(timeoutFn);
          // 重置定时器
          timeoutFn = (() => {
              fn.apply(this, arguments)
          },waitTime)
     }
}

function appendCount(){
    ELem.innerHTML=count++;
}

Elem.addEventListener('mousemove', debounce(appendCount, 500))

防抖流程

  • mousemove触发,触发debounce()`
  • 定义一个定时器timeoutFn,返回执行内容为:清除当前timeoutFn定时器( timeoutFn = null;),定义执行内容。

    // debounce() 返回内容
    function (){
          // 清空定时器
          clearTimeout(timeoutFn);
          // 重置定时器
          timeoutFn = (() => {
              fn.apply(this, arguments)
          },waitTime)
     }
  • mousemove再触发,timeoutFn定时器再次清空,重新定义执行内容
  • 只有等到最后一次mousemove,定时器没有被debounce()清除timeoutFn定时器,最后执行 fn.apply(this, agruments);

节流

相对比防抖,我是这样理解节流的:当我们想触发在
一段时间范围有且只触发一次这样的事件,这样我们可以更节约我们的资源和网络请求。

就当上面的AppendCount()举例,我只想在3s内之能触发一次事件AppendCount()

那么应该怎么处理呢?

var count = 0,
    Elem = doc.getElementById('con');

function throttle(fn,waitTime){
    var timeoutFn = null;
     
    return function () {
        // 如果存在timeoutFn定时器,则等待timeoutFn执行完成
        if(!timeoutFn){
            timeoutFn = (() => {
                // 置空定时器
                clearTimeout(timeoutFn)
                fn.apply(this, arguments)
            },waitTime)
        }     
    }
}

function appendCount(){
    ELem.innerHTML=count++;
}

Elem.addEventListener('mousemove', throttle(appendCount, 3000))

这和防抖不同的是,是等待timeoutFn执行完成后,通过clearTimeout(timeoutFn)置空,那么在3s后才能再次执行timeoutFn

还有一个写法,和上面有一点不同,上面的是当在第1s触发throttle,但是要在第4s才能执行appendCount。但是下面是立即执行,当第1s触发throttle,就执行appendCount,然后在第4s后可以再次会发throttle

var count = 0,
    Elem = doc.getElementById('con');

function throttle(fn, waitTime){
    // 定义定时器、执行状态
    var timeoutFn = null,
        isRuning = false;
     
    return function () {
        // 如果不在执行状态
       if(!isRuning){
           // 开启执行状态
           isRuning = true;
           // 定义定时器
           timeoutFn =(() => {
              fn.apply(this, arguments);
              // 执行完成,关闭执行状态
              isRuning = false;
           },waitTime)
       }
    }
}

function appendCount(){
    ELem.innerHTML=count++;
}

Elem.addEventListener('mousemove', throttle(appendCount, 3000))

参考

    原文作者:Kisnnnn
    原文地址: https://segmentfault.com/a/1190000019884659
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞