JS之防抖和节流

防抖 (debounce)

所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。

ps: 重置普攻,百度翻译要输完停止一定时间后才翻译。

没有防抖和节流的缺点

  1. 函数触发频率过高导致的响应速度跟不上触发频率,出现延迟,假死或卡顿的现象。
  2. 浪费请求资源

策略

当事件被触发时,设定一个周期延时执行动作,若周期又被触发,则重新设定周期,直到周期结束,执行动作。

在后期有拓展了前缘防抖函数,即执行动作在前,设定延迟周期在后,周期内有事件被触发,不执行动作,且周期重新设定。

案例 :停止输入后将输入的字符串翻转

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>防抖 </title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    html,
    body {
      height: 100%;
    }

    body {
      display: flex;
      justify-content: center;
      align-items: center;
    }

    .container {
      display: flex;
      justify-content: space-around;
      width: 800px;
      height: 400px;
      padding: 20px;
      box-shadow: 0 0 8px #222;
    }

    .container div {
      width: 350px;
      height: 380px;
      padding: 8px;
      border: 1px solid #ccc;
      font-size: 18px;
      line-height: 20px;
      word-break: break-all;
    }

    .input-box {
      color: #368;
      outline: none;
    }

    .show-box {
      color: orange;
    }
  </style>
</head>

<body>
  <div class="container">
    <div class="input-box" contenteditable></div>
    <div class="show-box"></div>
  </div>
  <script>
    var oInput = document.querySelector('.input-box')
    var oShow = document.querySelector('.show-box')
    var timeOut;//这个timeOut必须是全局变量
oInput.addEventListener('input', function () {
    timeOut && clearTimeout(timeOut);
    timeOut = setTimeout(function () {
        oShow.innerText = translate(oInput.innerText);
    }, 500);
}, false);

function translate(str) {
    return str.split("").reverse().join("");
}
  </script>
</body>

</html>

节流 (throttling)

所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。**节流会稀释函数的执行频率。

对于节流,有多种方式可以实现 时间戳 定时器 束流等。

ps : 技能CD

应用场景:

  1. 鼠标连续不断地触发某事件(如点击),只在单位时间内只触发一次;

  2. 在页面的无限加载场景下,需要用户在滚动页面时,每隔一段时间发一次 ajax 请求,而不是在用户停下滚动页面操作时才去请求数据;

  3. 监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断;

策略:

固定周期内,只执行一次动作,若没有新事件触发,不执行。周期结束后,又有事件触发,开始新的周期。
特点

连续高频触发事件时,动作会被定期执行,响应平滑

计时器版

javascript 复制代码
var oCon = $('.container');
var num = 0;
var valid = true;
oCon.addEventListener('mousemove', function () {
    if (!valid) {
        return false;
    }
    valid = false;
    setTimeout(function () {
        count();
        valid = true;
    }, 500);
}, false);

function count() {
    oCon.innerText = num++;
}

时间戳版

javascript 复制代码
var oCon = $('.container');
var num = 0;
var time = Date.now();
oCon.addEventListener('mousemove', function () {
    if (Date.now() - time < 600) {
        return false;
    }
    time = Date.now();
    count();
}, false);

function count() {
    oCon.innerText = num++;
}

束流器版

一般用在游戏中,元素以不同频率运动

这样做的好处是可以把所有元素用同一个定时器来管理,用速差来做不同频率的运动

javascript 复制代码
var oCon = $('.container');
var num = 0;
var time = 0;
oCon.addEventListener('mousemove', function () {
    time++;
    if (time % 30 !== 0) {
        return false;
    }
    console.log(time)
    count();
}, false);

function count() {
    oCon.innerText = num++;
}

案例:同一个定时器中 红色小球运动两次 蓝色小球运动一次

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>定时器运动 </title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    html,
    body {
      height: 100%;
    }

    div {
      position: absolute;
      width: 100px;
      height: 100px;
      border-radius: 50%;
    }

    .red {
      top: 100px;
      background-color: red;
    }

    .blue {
      background-color: blue;
    }
  </style>
</head>

<body>
  <div class="red"></div>
  <div class="blue"></div>
  <script src="js/common.js"></script>
  <script>
    var oRed = $('.red');
    var oBlue = $('.blue');
    var speed = 0;
    var counter = 0;
    var time;

    time = setInterval(function () {
      speed += .1;
      counter++;
      oRed.style.left = oRed.offsetLeft + speed
        + 'px';
      if (counter % 2 === 0) {
        oBlue.style.left = oBlue.offsetLeft + speed
          + 'px';
      }
    }, 1000 / 30);
  </script>
</body>

</html>
相关推荐
Larcher4 小时前
React Router 不只是页面跳转:从 SPA 路由到权限守卫的完整实践
javascript·后端
Larcher4 小时前
大模型为什么每次回答都不一样?一文搞懂 Temperature、Top K 与 Top P
javascript·后端
eric-sjq8 小时前
10 分钟实战:用 0.6B 本地模型生成中文网页(WanlyFrontend + 编译器全流程)
javascript·机器学习·自然语言处理·html
To_OC8 小时前
LC 438 找到所有字母异位词:暴力超时后,我靠滑动窗口一招搞定
javascript·算法·leetcode
kyriewen9 小时前
面试官问"这段逻辑为什么这样写"——我才发现,这半年我写的代码,我自己都解释不了
前端·javascript·面试
一壶浊酒..10 小时前
Scrape Webpack练习
开发语言·javascript·webpack
默_笙13 小时前
⛵ 我用 React + TS 做了个"调色盘",顺便学会了企业级项目的目录架构
前端·javascript
渣波13 小时前
拒绝 Redux 样板代码:Zustand 核心原理与实战进阶指南(基础、异步与切片模式)
前端·javascript
C++、Java和Python的菜鸟13 小时前
第12章 前端Web进阶(Vue工程化+ElementPlus)
前端·javascript·vue.js
妙码生花14 小时前
让各大 AI 整理出来的前端工程命名最简实践(Vue + TS)
前端·javascript·vue.js