如何实现防抖节流?

一、实现防抖:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。

比如说一个倒计时按钮,倒计时10秒,过了两秒,有人再次触发按钮,又要重新计时,再等10秒。

实现防抖思路:通过闭包维护一个变量,此变量代表是否已经开始计时,如果已经开始计时则清空之前计时器,重新计时。

    <script>
        // 首先闭包里面要有一个变量,这个变量是个计时器,
        // 我们要判断这个计时器是否已经计时了,如果已经
        // 计时了我们就把原先的清空掉
        // 不管有没有计时器,我们设置一个计时器,然后把函数和时间传进来
        // 传进来的函数有参数,还有this指向,用arguments和apply
            function debounce(fn, time) {
        let timer = null;
        return function() {
          let args = arguments;
          let context = this;
          if (timer) {
            clearTimeout(timer);
            timer = null;
          }
          timer = setTimeout(function() {
            fn.apply(context, args);
          }, time);
        };
      }
      function test(num) {
        console.log(num);
        console.log(this);
      }
      let newFn = debounce(test, 1000);
      window.onscroll = function() {
        newFn(123);
      };
    </script>
// 这个案例就是展示搜索框内容提示,为避免不必要的请求,设置一个定时器,
// 800 毫秒向服务器发送一次请求,如果期间文本框值发生变化,则清空计时器,不发送请求。
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>搜索框输入文字自动提示</title>
    <link
      rel="stylesheet"
      href="//www.greatytc.com/assets/bootstrap/dist/css/bootstrap.min.css"
    />
    <style type="text/css">
      .container {
        padding-top: 150px;
      }

      .list-group {
        display: none;
      }
    </style>
  </head>

  <body>
    <div class="container">
      <div class="form-group">
        <input
          type="text"
          class="form-control"
          placeholder="请输入搜索关键字"
          id="search"
        />
        <ul class="list-group" id="list-box"></ul>
      </div>
    </div>
    <script src="/js/ajax.js"></script>
    <script src="/js/template-web.js"></script>
    <script type="text/html" id="tpl">
      {{each data}}
      <li class="list-group-item">{{$value}}</li>
      {{/each}}
    </script>
    <script>
      // 获取搜索框
      var searchInp = document.getElementById("search");
      // 获取提示文字的存放容器
      var listBox = document.getElementById("list-box");
      // 存储定时器的变量
      var timer = null;
      searchInp.oninput = function() {
        clearTimeout(timer);
        var key = this.value;
        if (key.trim().length == 0) {
          listBox.style.display = "none";
          return;
        }
        timer = setTimeout(function() {
          ajax({
            type: "get",
            url: "http://localhost:3000/searchAutoPrompt",
            data: {
              key: key
            },
            success: function(data) {
              var html = template("tpl", { data: data });
              console.log(data);

              listBox.innerHTML = html;
              listBox.style.display = "block";
            }
          });
        }, 600);
      };
    </script>
  </body>
</html>

二、实现节流:在一段时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被多次触发,只能有一次生效。

例如发送验证码倒计时按钮,必须等够多少秒后才可以再次发送。

实现思路:通过闭包维护一个变量,次变量代表是否允许执行函数,如果允许则执行函数并且把该变量修改为不允许,并使用定时器在规定时间后恢复变量。

     <script>
      function throttle(fn, time) {
        let canRun = true; //是否允许fn 函数被执行
        return function() {

          if (canRun) {
            fn.apply(this, arguments);
            canRun = false;
            setTimeout(function() {
              canRun = true;
            }, time);
          }
        };
      }
      function test(num) {
        console.log(num);
        console.log(this.age);
      }
      let obj = {
        age: 18
      };
      let newFn = throttle(test, 2000);
      obj.newFn = newFn;
      window.onscroll = function() {
        obj.newFn("123");
      };
    </script>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 一.什么是函数防抖&节流 函数防抖函数防抖(debounce):在事件被触发n秒后再执行回调,如果在这n秒内又被触...
    王蕾_fd49阅读 440评论 0 1
  • 夜里睡眠质量太好,早上五点醒了就睡不着了。我跟先生是截然不同的两个人,他如果五点多醒,就会大想特想“自己睡眠质量不...
    乡下妞阅读 697评论 0 2
  • 说起黑客,大家应该都听说过,不少人肯定还会想到美国大片里这样一个场景:电脑屏幕上显示多个窗口,一名黑客的手指在键盘...
    一点新V阅读 517评论 0 1
  • tighten [ˈtʌɪt(ə)n] vt.使变紧缝紧收紧使更严格 vi.变紧绷紧变得更严格 英译:make t...
    浪徒i阅读 565评论 0 0
  • 突然发现我不但自闭,还有点不正常。 反正这个世界不就是需要一些不正常的疯子吗?
    24y阅读 211评论 0 0