前端常见之防抖与节流详解

67 阅读3分钟

防抖,节流

学习过程中的简单记录,若问题敬请指教!文章持续更新中...

路过的朋友,可以点个赞,关注一下~~~

定义

防抖:n秒后再执行该事件,若在n秒内被重复触发,则重新计时

节流:n秒内只运行一次,若在n秒内重复触发,只有一次有效

区别

相同点:

  • 都可以通过使用 setTimeout 实现
  • 目的都是,降低回调执行频率。节省计算资源

不同点:

  • 函数防抖,在一段连续操作结束后,处理回调,利用clearTimeoutsetTimeout实现。函数节流,在一段连续操作中,每一段时间只执行一次,频率较高的事件中使用来提高性能
  • 函数防抖关注一定时间连续触发的事件,只在最后执行一次,而函数节流一段时间内只执行一次

例如,都设置时间频率为500ms,在2秒时间内,频繁触发函数,节流,每隔 500ms 就执行一次。防抖,则不管调动多少次方法,在2s后,只会执行一次

如下图所示:

设计防抖

防抖主要是使用延时器来实现的,正常防抖可以分为两种分别是立即执行版本非立即执行版本。此处主要是结合两种形式的一个组合版本。

  • 立即执行版本:一般用在按钮点击上(比如提交表单),点击立即触发,单位时间内一直点击不会触发。当超过单位时间再次点击会再次触发。

  • 非立即执行版本:一般用在搜索联想功能中,输入内容的时候不触发,输入完后再请求后端获取数据。

export function debounce(func, delay, immediate = true) {
  let timer = null;
  return function () {
    // 上下文参数
    const context = this;
    const args = arguments;
    // 清除延时器
    if (timer) clearTimeout(timer);

    if (immediate) {
      // 立即执行版本
      const canCall = !timer;
      timer = setTimeout(() => {
        timer = null;
      }, delay);

      if (canCall) func.canCall(context, ...args);
    } else {
      // 非立即执行版本
      timer = setTimeout(() => {
        func.call(context, ...args);
      });
    }
  };
}

设计节流

节流也是使用延时器来实现的

使用场景

常见的使用场景是在一些 scroll 函数的事件监听上,通过事件节流来降低事件调用的频率。

// 实现节流
export function throttle(func, delay) {
  let timer = null;
  return function () {
    const context = this;
    const args = arguments;
    if (!timer) {
      timer = setTimeout(() => {
        timer = null;
        func.call(context, ...args);
      }, delay);
    }
  };
}

VUE中简单使用

通过外部引入的方式

防抖

import { debounce } from "@/utils/index";
export default {
  mounted() {
    window.addEventListener("scroll", this.handleScroll);
  },
  methods: {
    handleScroll: debounce(function (e) {
      console.log(e);
    }, 1000),
  },
};

节流

import { throttle } from "@/utils/index";
export default {
  mounted() {
    window.addEventListener("scroll", this.handleScroll);
  },
  methods: {
    handleScroll: throttle(function (e) {
      console.log(e);
    }, 1000),
  },
};

写在本文件里面

防抖

  mounted() {
    window.addEventListener("scroll", this.debounce(this.handleScroll, 1000));
  },
  methods: {
    debounce(func, delay) {
      let timer = null;
      return function () {
        const context = this;
        const args = arguments;
        if (timer) clearTimeout(timer);
        timer = setTimeout(() => {
          func.apply(context, args);
        }, delay);
      };
    },
    handleScroll(e) {
      console.log(e);
    },
  },

节流

  mounted() {
    window.addEventListener("scroll", this.throttle(this.handleScroll, 1000));
  },
  methods: {
    throttle(func, delay) {
      let timer = null;
      return function () {
        const context = this;
        const args = arguments;
        if (timer) clearTimeout(timer);
        timer = setTimeout(() => {
          func.apply(context, args);
        }, delay);
      };
    },
    handleScroll(e) {
      console.log(e);
    },
  },

后记

本文纯仅属于个人的一些简单的见解,比较浅显,若有不妥之处还请不吝赐教!!!(☆_☆)

如果本文对你有所帮助,欢迎点赞!!!

o( ̄▽ ̄)d