防抖与节流函数的封装

1. 防抖

我们在平时开发的时候,会有很多的场景会频繁触发事件,比如说搜索框实时发送请求。

oumousemove、resize、onscroll等等,有些时候我们并不想频繁触发事件,咋办呢?这个时候我们就可以用到函数的防抖和节流了。

1. 直接使用underscore.js来实现这些功能。
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    #container {
      width: 100%;
      height:200px;
      line-height: 200px;
      text-align: center;
      color:#fff;
      background-color: #444;
      background-size: 30px;
    }
  </style>
</head>
<body>
  <div id="container"></div>
  <script src="https://cdn.bootcss.com/underscore.js/1.9.1/underscore.js"></script>
  <script>
    // 演示事件是如何频繁发生的
    let count = 0;
    let container = document.querySelector('#container')
    function doSomething() {
      // 可能会做回调或者ajax请求
      container.innerHTML = count++;
    }
    // 防抖函数
    // container.onmousemove = _.debounce(doSomething, 1000);
    container.onmousemove = _.debounce(doSomething, 1000, true);

    // 防抖原理
    // 事件响应函数在一段时间之后才执行,如果在这段时间内再次调用,则重新计算执行时间
    // 当预定的时间内没有再次调用该函数,则执行doSomething函数
  </script>

</body>
</html>
2. 实现简单的防抖函数
function debounce(func,wait) {
  let timeout;
  return function() {
    clearTimeout(timeout);
    timeout = setTimeout(func, wait); // 定时器的id 为 timeout
  }
}

let count = 0;
// 演示事件是如何频繁发生的
let container = document.querySelector('#container');
function doSomething() {
// 可能会做回调或者ajax请求
  container.innerHTML = count++;
}

// 高阶函数 防抖
container.onmousemove = debounce(doSomething, 300)

就是每次触发事件的将上次的定时器任务取消,这样就不会在短时间事件被频繁触发。

4. 防抖的初步实现
// 防抖的函数
function debounce(func, wait, immediate) {
  let timeout;
  return function() {
    // console.log(arguments);
    // 改变执行函数内部 this 的指向
    // console.log(this); // container容器对象
    let context = this;
    // 获取执行函数的实参
    let args = arguments;

    clearTimeout(timeout); // 每次触发事件就先取消定时器
    if(immediate) {
      let callNow = !timeout; // 通过对timeout变量取反 判断是否立即执行(一开始 timeout 为 undefined,则布尔值为false)
      timeout = setTimeout(() => {
        timeout = null; // 通过对timeout变量置空来设置下一次的立即执行
      }, wait);
      // 立即执行,并改变this的指向
      if (callNow) func.apply(context, args)
      
    } else {
      // 不会立即执行
      timeout = setTimeout(function() {
        func.apply(context, args); 
      }, wait);
    }
    
  }
}

// 演示事件是如何频繁发生的
let count = 0;
let container = document.querySelector('#container')
function doSomething(e) {
  // e 是事件对象
  console.log(e)

  // console.log(this)  // container容器对象

  // 可能会做回调或者ajax请求
  container.innerHTML = count++;
}
// 防抖函数
// container.onmousemove = debounce(doSomething, 1000, true); // true 立即执行(只要鼠标进去就立即执行)
container.onmousemove = debounce(doSomething, 1000);
5. 防抖函数中的返回值和取消操作实现
function debounce(func, wait, immediate) {
  var timeout, result; 
  let decounced = 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;
  }
  decounced.cancel = function () {
    clearTimeout(timeout);
    timeout = null;
  }
  return decounced;
}

let count = 0;
let container = document.querySelector('#container')
let btn = document.querySelector('#btn')
function doSomething(e) {
  // e 是事件对象(要注意event的指向问题)
  console.log(e)

  // 改变执行函数内部this的指向问题
  // console.log(this)  // container容器对象

  // 可能会做回调或者ajax请求
  container.innerHTML = count++;
  return '想要的结果';
}
let doSome = debounce(doSomething, 10000)
btn.onclick = function () {
  doSome.cancel()
}


// 防抖函数
// container.onmousemove = debounce(doSomething, 1000, true); // true 立即执行(只要鼠标进去就立即执行)
container.onmousemove = doSome;

总结:

  1. 事件响应函数(doSomething) 在一段时间后(300ms)才执行,如果在这段时间内再次调用,则重新计算执行时间;当预定的时间内
  2. 应用场景:
    • scroll 事件滚动触发
    • 搜索框输入查询
    • 表单验证
    • 按钮提交事件
    • resize (浏览器的窗口缩放)

2. 节流

原理:如果持续的去触发事件,每隔一段时间只会执行一次事件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值