复习前端之防抖和节流

183 阅读2分钟

防抖应用场景:

1、输入框中频繁的输入内容,搜索或 者提交信息;
2、频繁的点击按钮,触发某个事件;
3、监听浏览器滚动事件,完成某些特 定操作;
4、用户缩放浏览器的resize事件等

节流应用场景:

1、监听页面的滚动事件
2、鼠标移动事件
3、用户频繁点击按钮操作等

理解防抖的过程

 当事件触发时,相应的函数并不会立即触发,而是会等待一定的时间,
 当事件密集触发时,函数的触发会被频繁的推迟;
 只有等待了一段时间也没有事件触发,才会真正的执行响应函数;

理解节流的过程

当事件触发时,会执行这个事件的响应函数
如果这个事件会被频繁触发,那么节流函数会按照一定的频率来执行函数
不管在这个中间有多少次触发这个事件,执行函数的频繁总是固定的

可以通过第三方库来实现防抖操作

 lodash
 underscore

使用underscore插件相关案例


    <script src="https://cdn.jsdelivr.net/npm/underscore@1.13.1/underscore-umd-min.js"></script>
    <script>
      let input = document.querySelector('input')
      let counter = 0
      let inputChange = function () {
        console.log(`监听第${counter++}次输入框事件`)
      }
      //   防抖的处理
      //_.debounce方法属于 underscore库里面的插件
      //   1000:触发时间
      //   input.oninput = _.debounce(inputChange, 1000)

      //   节流的处理
      input.oninput = _.throttle(inputChange, 1000)
    </script>

模拟underscore插件中debounce防抖函数

function debounce (fn, delay) {
  // 1.定义一个定时器,保存上一次的定时器
  let timer = null
  // 2.真正执行的函数
  let  _debounce = function (...args) {
  // 3。取消上一次的定时器
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => {
      fn.apply(this,args)
    }, delay)
  }
  return  _debounce
}

// fn:传入的函数
// delay:传入的时间
// args:调用传参
//  fn.apply(this,args):拿到当前调用者的this

立即执行函数之防抖(true为立即执行)

function debounce (fn, delay, immediate = false) {
  let timer = null
  let isInvoke = false
  const _debounce = function () {
    if (timer) clearTimeout(timer)

    // 判断是否需要立即执行
    if (immediate && !isInvoke) {
      fn.apply(this)
      isInvoke = true
    } else {
      // 延迟执行
      timer = setTimeout(() => {
        fn.apply(this)
        isInvoke = false
      }, delay)
    }
  }
  return _debounce
}

// 调用
// input:获取的DOM
// oninput:监听的事件
// inputChange:事件函数的调用

 input.oninput = debounce(inputChange, 1000, true)

立即执行函数+取消按钮

function debounce (fn, delay, immediate = false) {
  let timer = null
  let isInvoke = false
  const _debounce = function () {
    if (timer) clearTimeout(timer)

    // 判断是否需要立即执行
    if (immediate && !isInvoke) {
      fn.apply(this)
      isInvoke = true
    } else {
      // 延迟执行
      timer = setTimeout(() => {
        fn.apply(this)
        isInvoke = false
        timer = null
      }, delay)
    }
  }

  //   封装取消功能
  _debounce.cancel = function () {
    if (timer) clearTimeout(timer)
    timer = null
    isInvoke = false
  }
  return _debounce
}

// 使用
  const debounceChange = debounce(inputChange, 1000, true)
  input.oninput = debounceChange

  let btn = document.querySelector('button')
  btn.onclick = function () {
  debounceChange.cancel()
   }

借鉴coderwhy思路,总结出来的,感谢coderwhy