美文网首页
JavaScript - 防抖

JavaScript - 防抖

作者: 明里人 | 来源:发表于2019-08-12 17:49 被阅读0次

    防抖的原理:在n秒后执行触发的事件,如果在n秒内又触发了这个事件,就以新触发事件的事件为准,n秒后再执行该事件。

    第一版:
    function debounce(func, wait) {
     var timeout;
     return function() {
       clearTimeout(timeout);
       timeout = setTimeout(func, wait);
     } 
    }
    
    this:

    在debounce函数中,this指向window对象,我们需要将this指向func逻辑函数。

    // 第二版
    function debounce(func, wait) {
      var timeout;
    
      return function() {
        var context = this;
        clearTimeout(timeout);
        timeout = setTimeout(function () {
          func.apply(context);
        }, wait);
      }
    }
    
    event对象:

    当使用debounce函数时,在func逻辑函数中打印event事件时,打印值为undefined,所以再修改一下代码:

    // 第三版
    function debounce(func, wait) {
      var timeout;
    
      return function() {
        var context = this;
        var args = arguments;
    
        clearTimeout(timeout);
        timeout = setTimeout(function() {
          func.apply(context,args);
        }, wait)
      }
    }
    
    立刻执行:

    有这样一个需求,希望立即执行函数,然后等到n秒后再重新出发执行。
    那我们加一个 immediate 参数判断是否立即执行。

    // 第四版
    function debounce(func, wait, immediate) {
      var timeout;
      
      return function() {
        var context = this;
        var args = arguments;
      
        if (timeout) clearTimeout(timeout);
        if (immediate) {
          var callNow = !timeout;
          timeout = setTimeout(function () {
            timeout = null;
          }, wait);
          if (callNow) func.apply(context,args);
        } else {
          timeout = setTimeout(function () {
            func.apply(context, args);
          }, wait)
        }
      }
    }
    
    返回值:

    逻辑函数func可能是有返回值的,所以我们要返回函数执行结果。但immediate为false时,执行的是setTimeout,将func.apply(context,args)赋值给变量,并将变量返回会一直是undefined,所以只在immediate为true时返回函数的执行结果。

    // 第五版
    function debounce(func, wait, immediate) {
      var timeout, result;
      
      return function() {
        var context = this;
        var args = arguments;
        
        if (timeout) clearTimeout(timeout);
        if (immediate) {
          var callNow = !timeout;
          timeout = setTimeout(function () {
            timeout = null;
          }, wait);
          if (callNow) result = func.apply(context, args);
        }
        else {
          timeout = setTimeout(function() {
            func.apply(context,args);
          }, wait);
        }
        return result;
      }
    }
    
    取消:

    我希望通过一个按钮,点击后,取消防抖,再去触发,就可以立即执行。

    // 第六版
    function debounce(func, wait, immediate) {
      var timeout, result;
      var debounced = function() {
        var context = this;
        var args = arguments;
        
        if (timeout) clearTimeout(timeout);
        if (immediate) {
          var callNow = !timeout;
          timeout = setTimeout(function() {
            timeout = null;
          }, wait);
          if (callNow) result = func.apply(context,args);
        }
        else {
          timeout = setTimeout(function () {
            func.apply(context,args);
          }, wait);
        }
        return result;
      }
      
      debounced.cancel = function() {
        clearTimeout(timeout);
        timeout = null;
      }
    
      return debounced;
    }
    

    如何使用这个cancel函数?

    // 例子:
    var count = 1;
    var container = document.getElementById('container');
    
    function getUserAction(e) {
        container.innerHTML = count++;
    };
    
    var setUseAction = debounce(getUserAction, 10000, true);
    
    container.onmousemove = setUseAction;
    
    document.getElementById("button").addEventListener('click', function(){
        setUseAction.cancel();
    })
    

    相关文章

      网友评论

          本文标题:JavaScript - 防抖

          本文链接:https://www.haomeiwen.com/subject/pgoujctx.html