漂亮的防抖与节流

JS防抖与节流快速了解与应用-云社区-华为云 (huaweicloud.com)

防抖三个阶段

1.1s后执行1次,多次点击不执行

2.首次点击执行,多次点击只执行第一次,(执行1次)

3.首次点击执行,多次点击只执行最后一次,(执行2次)

1-

<template>
  <div>
    <el-button id="btn">catchMe</el-button>
  </div>
</template>

<script>
export default {
  mounted() {
    let btn = document.getElementById("btn");
    btn.addEventListener("click", trigger(real, 1000));
    function trigger(fn, delay) {
      let time = null;
      return function () {
        // *FirstClick execute.
        // let firstClick = !time;
        // firstClick && fn(...arguments);

        if (time) {
          clearTimeout(time);
        }
        // reset timer(定时器clock)
        // now time is not null, firstClick is null
        // But it should be null when the next time to click.
        time = setTimeout(() => {
          // *firstClick become the start flag to clickMethod.
          fn(...arguments);
        //   time = null;
          // **When timer clear and the last click need to be executed.
        //   !firstClick && fn(...arguments);
        }, delay);
      };
    }
    function real(e) {
      console.log("debounce", e);
    }
  },
};
</script>
View Code

2-

<template>
  <div>
    <el-button id="btn">catchMe</el-button>
  </div>
</template>

<script>
export default {
  mounted() {
    let btn = document.getElementById("btn");
    btn.addEventListener("click", trigger(real, 1000));
    function trigger(fn, delay) {
      let time = null;
      return function () {
        // *FirstClick execute.
        let firstClick = !time;
        firstClick && fn(...arguments);

        if (time) {
          clearTimeout(time);
        }
        // reset timer(定时器clock)
        // now time is not null, firstClick is null
        // But it should be null when the next time to click.
        time = setTimeout(() => {
          // *firstClick become the start flag to clickMethod.
        //   fn(...arguments);
          time = null;
          // **When timer clear and the last click need to be executed.
        //   !firstClick && fn(...arguments);
        }, delay);
      };
    }
    function real(e) {
      console.log("debounce", e);
    }
  },
};
</script>
View Code

3-

<template>
  <div>
    <el-button id="btn">catchMe</el-button>
  </div>
</template>

<script>
export default {
  mounted() {
    let btn = document.getElementById("btn");
    btn.addEventListener("click", trigger(real, 1000));
    function trigger(fn, delay) {
      let time = null;
      return function () {
        // *FirstClick execute.
        let firstClick = !time;
        firstClick && fn(...arguments);

        if (time) {
          clearTimeout(time);
        }
        // reset timer(定时器clock)
        // now time is not null, firstClick is null
        // But it should be null when the next time to click.
        time = setTimeout(() => {
          // *firstClick become the start flag to clickMethod.
          // fn(...arguments);
          time = null;
          // **When timer clear and the last click need to be executed.
          !firstClick && fn(...arguments);
        }, delay);
      };
    }
    function real(e) {
      console.log("debounce", e);
    }
  },
};
</script>
View Code

节流 

高强度点击按钮,每1s生成一次提示

时间戳版本

<template>
  <div>
    <el-button id="btn">needYou</el-button>
  </div>
</template>

<script>
export default {
  mounted() {
    let btn = document.getElementById("btn");
    btn.addEventListener("click", trigger(real, 1000));
    function trigger(fn, delay) {
      // last executed time
      let bef = 0;
      return function () {
        // get recent time
        let now = new Date().getTime();
        // When time has arrived, it exectues and bef reset.
        if (now - bef > delay) {
          fn(...arguments);
          bef = now;
        }
      };
    }
    function real() {
      console.log("I need you.");
    }
  },
};
</script>
View Code

定时器版本

<template>
  <div>
    <el-button id="btn">needYou</el-button>
  </div>
</template>

<script>
export default {
  mounted() {
    let btn = document.getElementById("btn");
    btn.addEventListener("click", trigger(real, 1000));
    function trigger(fn, delay) {
      let flag = true;
      return function () {
        // Frist click, it will delay to execute.
        flag &&
          setTimeout(() => {
            fn(...arguments);
            flag = true;
          }, delay);
        // Flag become false, timer will not start.
        // Until the next time click.
        flag = false;
      };
    }
    function real() {
      console.log("I need you.");
    }
  },
};
</script>
View Code

 

使用

对一个el-button使用防抖,多次点击只执行首次

// DebounceBtn.vue

<template>
  <div>
    <el-button class="click">click</el-button>
    count:{{ count }}
  </div>
</template>

<script>
import { debounce } from "../utils/utils";
export default {
  data() {
    return {
      count: 0,
    };
  },
  mounted() {
    let btn = document.getElementsByClassName("click")[0];
    btn.addEventListener("click", debounce(this.handleClick, 1000));
  },
  methods: {
    handleClick() {
      this.count = this.count + 1;
    },
  },
};
</script>

<style>
</style>
View Code

// /utils/utils.js

/**
 * @param {Function} func
 * @param {number} wait
 * @param {boolean} immediate
 * @return {*}
 */
export function debounce(func, wait) {
    console.log('debounce count');
    let time = null;
    return function () {
        let firstClick = !time;
        firstClick && func(...arguments);

        if (time) {
            clearTimeout(time);
        }
        time = setTimeout(() => {
            time = null;
        }, wait)
    }
}
View Code

 

可用防抖版本

 

 

总结——

防抖就是通过setTimeout 的方式,在一定的时间间隔内,将多次触发变成一次触发 。

节流:就是减少一段时间的触发频率。

防抖与节流最大的区别就是,无论事件触发多么频繁,都可以保证在规定时间内可以执行一次执行函数。防抖首尾自定义执行,节流点击途中一直有隔着相应时间间隔的执行。

posted @ 2021-10-20 11:23  乐盘游  阅读(52)  评论(0编辑  收藏  举报