• 函数防抖与节流


    在进行窗口的resize、scroll,输入框内容校验等操作时,如果事件处理函数调用的频率无限制,会加重浏览器的负担,导致用户体验非常糟糕。此时我们可以采用debounce(防抖)和throttle(节流)的方式来减少调用频率,同时又不影响实际效果。

    函数防抖(debounce)

    函数防抖(debounce):
    当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。如下图,持续触发scroll事件时,并不执行handle函数,当1000毫秒内没有触发scroll事件时,才会延时触发scroll事件。

    在第一次触发事件时,不立即执行函数,而是给出一个期限值比如200ms,然后:

    • 如果在200ms内没有再次触发滚动事件,那么就执行函数
    • 如果在200ms内再次触发滚动事件,那么当前的计时取消,重新开始计时

    效果:
    如果短时间内大量触发同一事件,只会执行一次函数。

    实现:
    函数防抖的基本思想是设置一个定时器,在指定时间间隔内运行代码时清楚上一次的定时器,并设置另一个定时器,知道函数请求停止并超过时间间隔才会执行。,由于还需要一个变量来保存计时,考虑维护全局纯净,可以借助闭包来实现。

    使用场景:
    文本框输入搜索(连续输入时避免多次请求接口)

    防抖debounce代码:

        /**
         * 防抖函数
         * @param {Fcuntion} fn 要执行的函数
         * @param {Number} delay 延迟执行的毫秒数,默认是200毫秒
         * @return {Function}    防抖函数
         */
        function debounce(fn, delay) {
          var timer = null;    //借助闭包
          var delay = delay || 200;
          return function() {
            var args = arguments;
            var that = this;
            // 清楚上一次的定时器
            if(timer){
                clearTimeout(timer)
            }
            timer = setTimeout(function() {
                fn.apply(that,args);
            }, delay);
          }
        }
    // 防抖函数 ES6写法
    const debounce = (fn, delay=200) => {
      let timer = null;    //借助闭包
      return function (...args) {
        if(timer){
            clearTimeout(timer)
        }
        timer = setTimeout(() => {
            fn.apply(this,args);
        }, delay);
      }
    }	
    	
    // 处理函数
    function handle(str){
    	console.log('write---',str,Date.now());
    }
    // 监听input输入change事件
    // 注意:如果防抖的函数不需要参数的话,可以使用第一种写法防抖,如果需要防抖的函数还需要传入参数,请使用第二种写法。
    //防抖第一种写法:
    $('input').on('input',debounce(handle,2000));
    
    //防抖第二种写法:
    var debounced = debounce(handle,2000);
    $('input').on('input',function(){
    	debounced($(this).val());
    });
    
    
    

    当持续触发scroll事件时,事件处理函数handle只在停止滚动1000毫秒之后才会调用一次,也就是说在持续触发scroll事件的过程中,事件处理函数handle一直没有执行。

    函数节流(throttle)

    函数节流(throttle):
    当持续触发事件时,保证一定时间段内只调用一次事件处理函数。规定在一个单位时间内,只能触发一次函数,如果这个单位时间内触发多次函数,只有一次生效; 典型的案例就是鼠标不断点击触发,规定在n秒内多次点击只有一次生效。

    效果:
    如果短时间内大量触发同一事件,那么在函数执行一次之后,该函数在指定的时间期限内不再工作,直至过了这段时间才重新生效。

    实现原理:
    其原理是用时间戳来判断是否已到回调该执行时间,记录上次执行的时间戳,然后每次触发 scroll 事件执行回调,回调中判断当前时间戳距离上次执行时间戳的间隔是否已经到达 规定时间段,如果是,则执行,并更新上次执行的时间戳,

    使用场景
    resize、scroll、mousemove等事件触发监听

    节流throttle代码:

        /**
         * 配置节流函数
         * @param  {Function}  fn   要执行的函数
         * @param  {Number}  delay  延迟执行的毫秒数,默认是200毫秒
         * @return {Function}       节流函数
         */
        function throttle(fn, delay) {
          // 上一次函数触发时间
          var lastTime;
          var timer = null;
          var delay = delay || 200;
          return function() {
            // 记录当前函数触发的时间
            var nowTime = Date.now();
            var context = this;
            var args = arguments;
            if (lastTime && nowTime - lastTime < delay) {
              // 如果上一次函数触发时间存在,并且现在触发时间与上一次触发时间差值小鱼delay
              // 说明触发时间太短,还没有到达规定的delay时间
              // 所以先清除上一次的定时器,重新设置延迟执行
              clearTimeout(timer);
              timer = setTimeout(function(){
                // 记录上一次函数触发的时间
                lastTime = nowTime;
                fn.apply(context, args);
              }, delay);
            } else {
              lastTime = nowTime;
              fn.apply(context, args);
            }
          }
        }
    	
    
    // 节流函数 ES6写法
    const throttle = (fn, delay=200) => {
      // 上一次函数触发时间
      let lastTime;
      let timer = null;
      // let delay = delay || 200;
      return function (...args)  {
        // 记录当前函数触发的时间
        let nowTime = Date.now();
        if (lastTime && nowTime - lastTime < delay) {
          // 如果上一次函数触发时间存在,并且现在触发时间与上一次触发时间差值小鱼delay
          // 说明触发时间太短,还没有到达规定的delay时间
          // 所以先清除上一次的定时器,重新设置延迟执行
          clearTimeout(timer);
          timer = setTimeout(() => {
            // 记录上一次函数触发的时间
            lastTime = nowTime;
            fn.apply(this, args);
          }, delay);
        } else {
          lastTime = nowTime;
          fn.apply(this, args);
        }
      }
    }	
    // 处理函数
    function handle(id){
         console.log('aa---',id,Date.now());
    }
    // 监听window的scroll事件
    // 注意:如果节流的函数不需要参数的话,可以使用第一种写法节流,如果需要节流的函数还需要传入参数,请使用第二种写法。
    //防抖第一种写法:
    $(window).on('scroll',throttle(handle, 3000));
    
    //防抖第二种写法:
    var throttled = throttle(aa,2000);
    $(window).on('scroll', function(){
    	throttled(99)
    });
    
    
    

    总结

    函数防抖(debounce):将几次操作合并为一此操作进行。原理是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置。这样一来,只有最后一次操作能被触发。

    函数节流(throttle):使得一定时间内只触发一次函数。原理是通过判断是否到达一定时间来触发函数。

    区别: 函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数。 比如在页面的无限加载场景下,我们需要用户在滚动页面时,每隔一段时间发一次 Ajax 请求,而不是在用户停下滚动页面操作时才去请求数据。这样的场景,就适合用节流技术来实现。

  • 相关阅读:
    题解CF566D Restructuring Company
    题解CF986F Oppa Funcan Style Remastered
    题解P2371 [国家集训队]墨墨的等式
    题解 CF1203D2 Remove the Substring (hard version)
    题解 CF1202D Print a 1337-string...
    ubuntu apt-get install php
    jwt refresh token
    读过的laravel文章
    delete all untracked files
    自定义UserProvider,更改验证方法
  • 原文地址:https://www.cnblogs.com/jiaoshou/p/13325224.html
Copyright © 2020-2023  润新知