防抖与节流

防抖

概念

  • 在n秒后执行事件响应函数,如果在n秒之内再次触发,将重新计算时间
  • (加入立即执行参数)第一次触发会立即执行一次,在n秒之内不再触发,才能继续触发执行

应用场景

  • scroll事件滚动触发
  • 搜索框输入查询
  • 表单验证
  • 按钮提交事件
  • 浏览器窗口缩放,resize事件

防抖函数中要实现的内容(源码中)

  • 实现防抖功能
  • this需要指向调用者
  • event事件对象的指向问题
  • 增加立即执行的参数
  • 函数中出现返回值
  • 取消防抖

代码实现

基础版

      // 防抖
      // 1 实现防抖功能
      // 2 this需要指向调用者
      // 3 event事件对象的指向问题
      function debounce(fn, wait) {
        let timer
        return function () {
          // 保存当前this,方便在定时器函数中修改this指向(定时器函数中的this指向window),这时this指向调用者;
          let context = this
          // arguments 是一个对应于传递给函数的参数的类数组对象(拿到传递给函数的所有参数并转化为数组对象)
          let args = arguments
          // 这里要注意clearTimeout会清除定时器(根据定时器的ID值进行清除),但不会影响由setTimeout返回的整数值timer,即下面一行代码执行后,timer仍然有值!!!
          if (timer) clearTimeout(timer)
          timer = setTimeout(function () {
            fn.apply(context, args)
          }, wait)
        }
      }

立即执行版

      // 防抖
      // 1 实现防抖功能
      // 2 this需要指向调用者
      // 3 event事件对象的指向问题
      // 4 增加立即执行的参数
      // 5 函数中出现返回值
      function debounce(fn, wait, immediate) {
        let timer, result
        return function () {
          // 保存当前this,方便在定时器函数中修改this指向(定时器函数中的this指向window),这时this指向调用者;
          let context = this
          // arguments 是一个对应于传递给函数的参数的类数组对象(拿到传递给函数的所有参数并转化为数组对象)
          let args = arguments
          // 这里要注意clearTimeout会清除定时器(根据定时器的ID值进行清除),但不会影响由setTimeout返回的整数值timer,即下面一行代码执行后,timer仍然有值!!!
          if (timer) clearTimeout(timer)
          if (immediate) {
            // 第一次触发,会立即执行一次,在n秒之内不再触发,才能继续触发执行
            let flag = !timer
            if (flag) result = fn.apply(context, args)
            timer = setTimeout(() => {
              // 等待wait时间后,将timer置空,这时就可以再次触发并立即执行
              timer = null
            }, wait)
          } else {
            timer = setTimeout(function () {
              result = fn.apply(context, args)
            }, wait)
          }
          return result
        }
      }

防抖的升级

在wait之内触发debounce n次之后立刻执行fn-----多益网络笔试

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <button>点击</button>
    <script>
      let btn = document.querySelector('button')
      // 防抖
      btn.onclick = debounce(fn, 5000, 2)

      function fn() {
        console.log('打印')
      }

      // 在wait之内触发debounce n次之后立刻执行fn
      let count = 0
      function debounce(fn, wait, n) {
        let timer
        return function () {
          let context = this
          let args = arguments
          if (timer) {
            count++
            clearTimeout(timer)
            if (count === n) {
              fn.apply(context, args)
              count = 0
              return
            }
          }
          timer = setTimeout(() => {
            fn.apply(context, args)
          }, wait)
        }
      }
    </script>
  </body>
</html>

节流

概念

在n秒之内只执行一次事件处理函数,无论在n秒之内触发多少次

应用场景

  • DOM元素的拖拽功能实现
  • 射击游戏
  • 计算鼠标移动距离
  • 监听scroll滚动事件

代码实现

时间戳实现

      // 1 时间戳实现
      // 第一次可以立即执行,最后一次不会自动触发执行
      function throttle(fn, wait) {
        let context, args
        let old = 0
        return function () {
          // 保存当前this,方便修改fn中的this指向
          // !!! 如果不进行this指向修改,fn()中的this会指向window,这里是为什么???现在还不太懂
          context = this
          args = arguments
          // 获取当前时间戳
          let now = new Date().valueOf()
          // 第一次一定执行,这样就实现了立即执行,再以后wait内只执行一次
          if (now - old > wait) {
            fn.apply(context, args)
            old = now
          }
        }
      }

定时器实现

      // 2 定时器实现
      // 第一次不会立即执行,最后一次会自动触发执行
      function throttle(fn, wait) {
        let context, args, timer
        return function () {
          context = this
          args = arguments
          if (!timer) {
            timer = setTimeout(() => {
              timer = null
              fn.apply(context, args)
            }, wait)
          }
        }
      }

定时器和时间戳实现

      // 3 结合时间戳和定时器的版本
      // 第一次立即执行,最后一次会自动触发执行
      function throttle1(fn, wait) {
        let context, args, timer
        let old = 0
        return function () {
          context = this
          args = arguments
          let now = new Date().valueOf()
          // 只在第一次触发时立即执行一次
          if (now - old > wait) {
            // 下面这个判断为什么,还有点不懂
            if (timer) {
              clearTimeout(timer)
              timer = null
            }
            fn.apply(context, args)
            old = now
          }
          if (!timer) {
            timer = setTimeout(() => {
              timer = null
              old = new Date().valueOf()
              fn.apply(context, args)
            }, wait)
          }
        }
      }

参考文献

https://www.bilibili.com/video/BV1pQ4y1M71e

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Vue中,有一些常用的防抖节流插件可以方便地实现防抖节流的功能。以下是两个常用的插件: 1. Lodash(防抖节流) Lodash是一个JavaScript实用工具库,它提供了许多常用的函数和方法,包括防抖节流函数。使用Lodash的`debounce`和`throttle`函数可以很方便地实现防抖节流。 安装Lodash: ```bash npm install lodash ``` 使用示例: ```javascript import { debounce, throttle } from 'lodash'; // 防抖示例 const debouncedFunc = debounce(() => { console.log('执行操作'); }, 500); // 节流示例 const throttledFunc = throttle(() => { console.log('执行操作'); }, 200); ``` 2. Vue-lodash(防抖节流) Vue-lodash是一个专门为Vue开发的Lodash插件,它提供了Vue指令的方式来使用Lodash的方法,包括防抖节流。 安装Vue-lodash: ```bash npm install vue-lodash ``` 在Vue项目中使用Vue-lodash示例: ```javascript import Vue from 'vue'; import VueLodash from 'vue-lodash'; import { debounce, throttle } from 'lodash'; Vue.use(VueLodash, { lodash: { debounce, throttle } }); ``` 在Vue组件中使用防抖节流: ```html <template> <div> <button v-debounce:click="debouncedFunc">点击按钮(防抖)</button> <button v-throttle:click="throttledFunc">点击按钮(节流)</button> </div> </template> <script> export default { methods: { debouncedFunc() { console.log('执行操作'); }, throttledFunc() { console.log('执行操作'); }, }, }; </script> ``` 以上是两个常用的Vue插件,可以方便地在Vue项目中使用防抖节流功能。根据具体需求选择合适的插件来使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值