2

前端都应该要掌握的防抖和节流 - 初见雨夜

 2 years ago
source link: https://www.cnblogs.com/rainy-night/p/16169285.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

说到防抖和节流相信大家都不陌生,这两个东西大家可能多多少少都有用到过,最少也有听过

古人云,温故而知新。虽然可能已经很熟悉防抖和节流了,但不妨再看一看巩固一下知识

什么?你说你不仅不会手写防抖和节流,也没有听过。那也没事,下文会详细介绍的

防抖和节流有什么用?

简单来说,防抖和节流都是用来减少函数执行的频率,以达到优化项目性能或者实现特定功能的效果

定义:事件被触发一定时间后再执行回调。如果在这段时间内又被触发了,则重新开始计算时间

  • 输入框远程查询事件
  • 在线文档自动保存
  • 浏览器视口大小改变

张三在某平台搜索一本书籍,发现搜索建议并不是瞬间就出现的,而是自己输入词组结束后出现的。那么该平台在此搜索框可能做了什么操作?

<body>
  <input type="text" id="searchElement" />
</body>
<script>
  const searchElement = document.getElementById('searchElement');
  const debounce = (fn, initial) => {
    let timer = null;
    return () => {
      clearTimeout(timer);
      timer = setTimeout(fn, initial);
    };
  };

  searchElement.oninput = debounce(function (event) {
    const value = searchElement.value;
    if (value) console.log(value, '请求值');
  }, 1000);
</script>

定义:在单位时间内只触发一次函数,若单位时间内多次触发只有一次生效

  • 按钮提交事件(当然也可做成点击后就loading)
  • 页面滚动事件的触发
  • 累计计算鼠标移动距离

张三参加某平台周年庆活动,他选购了某热门饮品并一直点击抢购按钮,却发现并不是每次点击都会有响应的。那么该平台前端可能做了什么限制?

<body>
  <button type="submit" id="buttonElement">抢购</button>
</body>
<script>
  function throttle(fn, interval) {
    let timer;
    return (event) => {
      if (timer) return false;
      timer = setTimeout(() => {
        clearTimeout(timer);
        timer = null;
        fn(event);
      }, interval);
    };
  }

  var btnClick = document.getElementById('buttonElement');
  btnClick.addEventListener('click', throttle(function (event) {
    console.log(event, '点击了')
  }, 1000));
</script>

可以看到,张三疯狂点击抢购,但还是每秒只响应1次

节流(立即执行)

细心的同学可能发现了,上面这个代码有个弊端,那就是在张三第一次点击的时候也隔了1秒才响应,这不免也太坑了。正常来说第一次应该直接响应的,并且在连续点击结束后的第一次也应该立即触发,其实想实现这样的效果也不难

<body>
  <button type="submit" id="buttonElement">抢购</button>
</body>
<script>
  function throttle2(fn, interval) {
      let init = false; // 引入一个参数记录状态
      let timer;
      return (event) => {
          if (init) return;
          init = true;
          clearTimeout(timer);
          timer = setTimeout(() => {
              init = false;
          }, interval);
          fn(event);
      }
  }

  var btnClick = document.getElementById('buttonElement');
  btnClick.addEventListener('click', throttle2(function (event) {
      console.log(event, '点击了')
  }, 2000));
</script>

可以看到第一次点击直接打印,第二次疯狂点击只打印一次,最后一次点击也是直接打印

引入Lodash实现

GitHub地址:https://github.com/lodash/lodash
官方文档:https://www.lodashjs.com/

防抖

import _ from 'lodash';
debounceHandle: _.debounce(function() {
  console.log('业务代码');
}, 2000, {       // 在n毫秒内触发
  leading: true, // 第一次点击立刻执行,默认为true
  trailing: true // 节流结束后立刻执行,默认为true
});

节流

import _ from 'lodash';
throttleHandle: _.throttle(function() {
  console.log("业务代码");
}, 2000);

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK