美文网首页
防抖和节流以及第三方插件lodash

防抖和节流以及第三方插件lodash

作者: 扶得一人醉如苏沐晨 | 来源:发表于2023-03-08 09:10 被阅读0次

防抖和节流的简单理解

节流相当于技能cd(一段时间内只能点击一次),
防抖相当于回城(你打断我我姐重新计时回城)。

一、防抖(debounce)

防抖,顾名思义,防止抖动,以免把一次事件误认为多次,敲键盘就是一个每天都会接触到的防抖操作。

1.1、原理

1)某个任务你并不想它太过频繁触发,那么设置一个指定间隔的定时器来延迟执行;
2)每次进来的时候都清除原本的定时器,然后重新开始计时;
3)只有任务触发的间隔超过指定间隔的时候,任务才会执行。

1.2、特点

1)如果在指定间隔内(如 1000ms)再次触发任务,那么当前的计时取消,所有任务不会执行,重新开始计时。
2)如果在指定间隔内(如 1000ms)没有再次触发任务,那么就执行最后一次任务
 也就是说,如果触发太过频繁,会导致一次响应都没有。只能等你最后一次触发结束指定间隔(如 1000ms)后,才能执行最后一次任务。

1.3、应用场景

1)登录、发短信等按钮避免用户点击太快,以致于发送了多次请求,需要防抖
2)调整浏览器窗口大小时,resize 次数过于频繁,造成计算过多,此时需要一次到位,就用到了防抖
3)文本编辑器实时保存,当无任何更改操作一秒后进行保存

1.4、代码实现

/**
 * 防抖
 * @param {String} fn 回调方法
 * @param {String} delay 缓冲时间
 */

function debounce(fn, delay) {
  // 创建一个标记用来存放定时器
  let timeout = null
  return function () {
    // 每次函数触发的时候,清空之前的定时器
    clearTimeout(timeout)
    // 创建一个新的 setTimeout
    // 这样就能保证点击按钮后的 delay 时间间隔内
    // 如果用户还点击了的话,就不会执行 fn 函数
    timeout = setTimeout(() => {
      // 使用apply修正 this 指向,执行传入函数
      fn.apply(this, arguments)
    }, delay)
  }
}

二、节流 (throttle)

节流,顾名思义,控制水的流量。控制事件发生的频率,如控制为 1s 发生一次,甚至 1 分钟发生一次。与服务端(server)及网关(gateway)控制的限流 (Rate Limit) 类似。

2.1、原理

1)初始化一个开关锁为真
2)设置闭包函数,函数内判断标记为真才执行,然后将标记置为假
3)闭包函数内一个指定间隔的定时器来延迟执行任务,执行完则再将标记置真;

2.2、特点

1)无论在指定间隔内(如 1000ms)触发多少次任务,只执行第一次任务
2)在触发任务的指定间隔(如 1000ms)之后,肯定执行第一次任务。
 也就是说,只要你触发一次任务,每在指定间隔(如 1000ms)之后肯定执行且只执行第一次;循环往复。

2.3、应用场景

1)scroll 事件,每隔一秒计算一次位置信息等
2)浏览器播放事件,每个一秒计算一次进度信息等
3)input 框实时搜索并发送请求展示下拉列表,每隔一秒发送一次请求 (也可做防抖)

2.4、代码实现

/**
 * 节流
 * @param {String} fn 回调方法
 * @param {String} delay 缓冲时间
 */

function throttle(fn, delay) {
  // 初始化一个状态为真
  let canRun = true
  return function () {
    // 判断状态,休息时间 暂不接客
    if (!canRun) {
      return
    }
    // 工作时间,执行函数;
    // 在间隔期内把状态位设为假
    canRun = false
    // 创建定时器,延迟执行任务
    setTimeout(() => {
      // 使用apply修正 this 指向,执行传入函数
      fn.apply(this, arguments)
      // 执行完任务之后,重新将这个标志设置为真
      canRun = true
    }, delay)
  }
}
 

三、总结

附演示代码

<div>
  <button id="debounceBtn">点我防抖</button>
  <button id="throttleBtn">点我节流</button>
</div>

<script>
  // 点击按钮次数
  let clickNum = 0
  // 按钮点击时间
  let clickTime = 0
  // 按钮开始点击时间
  let startTime = 0
  // 执行时间
  let executionTime = 0
  // 获取按钮
  const debounceBtn = document.getElementById('debounceBtn')
  const throttleBtn = document.getElementById('throttleBtn')
  // 绑定点击事件
  debounceBtn.onclick = function (e) {
    clickBtn()
    debounceFn(clickNum)
  }
  throttleBtn.onclick = function (e) {
    clickBtn()
    throttleFn(clickNum)
  }

  // 节流及防抖事件
  let debounceFn = debounce(fnExecution, 1000)
  let throttleFn = throttle(fnExecution, 1000)

  // 点击按钮事件
  function clickBtn() {
    clickNum++
    clickTime = Date.now()
    if (clickNum === 1) {
      startTime = Date.now()
    }
    console.log(`这是第${clickNum}次点击`)
  }

  function fnExecution(num) {
    executionTime = Date.now()
    console.log(
      `生效的是第 ${num}次点击,生效时间与最后一次点击隔时间为${
        executionTime - clickTime
      }毫秒,生效时间与第一次点击隔时间为${executionTime - startTime}毫秒`
    )
    clickNum = 0
  }

  /**
   * 防抖
   * @param {String} fn 回调方法
   * @param {String} delay 缓冲时间
   */

  function debounce(fn, delay) {
    // 创建一个标记用来存放定时器
    let timeout = null
    return function () {
      // 每次函数触发的时候,清空之前的定时器
      clearTimeout(timeout)
      // 创建一个新的 setTimeout
      // 这样就能保证点击按钮后的 delay 时间间隔内
      // 如果用户还点击了的话,就不会执行 fn 函数
      timeout = setTimeout(() => {
        // 使用apply修正 this 指向,执行传入函数
        fn.apply(this, arguments)
      }, delay)
    }
  }

  /**
   * 节流
   * @param {String} fn 回调方法
   * @param {String} delay 缓冲时间
   */

  function throttle(fn, delay) {
    // 初始化一个状态为真
    let canRun = true
    return function () {
      // 判断状态,休息时间 暂不接客
      if (!canRun) {
        return
      }
      // 工作时间,执行函数;
      // 在间隔期内把状态位设为假
      canRun = false
      // 创建定时器,延迟执行任务
      setTimeout(() => {
        // 使用apply修正 this 指向,执行传入函数
        fn.apply(this, arguments)
        // 执行完任务之后,重新将这个标志设置为真
        canRun = true
      }, delay)
    }
  }
</script>

四、插件lodash实现防抖和节流(推荐)

lodash插件:里面封装函数的防抖与节流与节流的业务【闭包+延迟器】
lodash函数库对外暴露_函数

如果没有可以安装一下

npm i --save lodash

4.1、使用

import _ from 'lodash'

语法

fn是你需要处理的方法,delay延迟时间

_.throttle(fn,delay)
_.debounce(fn,delay)

相关文章

网友评论

      本文标题:防抖和节流以及第三方插件lodash

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