防抖和节流

简介

节流和防抖是前端面试中老生常谈的话题,能大大提升程序的性能。但是节流防抖具体是什么?什么情况下使用呢?以及在Vue中应该怎么使用呢?下面请跟随笔者的脚步给大家逐步介绍。

防抖(debounce)

所谓防抖,就是指单位时间内函数只执行一次,如果在单位时间内重复触发该事件,则会重新计算函数执行时间。

防抖又分为两种,分为立即执行版本和非立即执行版本。

立即执行版本

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

function debounce1(func, delay) {
  let timer = null
  return function() {
    const context = this
    const args = arguments
    if(timer) clearTimeout(timer)
    const canCall = !timer
    timer = setTimeout(() => {
      timer = null
    }, delay)
    
    // if(canCall) func.apply(context, args)
    if(canCall) func.call(context, ...args)
  }
}
复制代码

非立即执行版本

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

function debounce2(func, delay) {
  let timer = null
  return function() {
    const context = this
    const args = arguments
    if(timer) clearTimeout(timer)
    timer = setTimeout(() => {
      //func.apply(context, args)
      func.call(context, ...args)
    },delay)
  }
}
复制代码

组合版本

function debounce3(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.apply(context, args)
      if(canCall) func.call(context, ...args)
    } else {
      timer = setTimeout(() => {
        //func.apply(context, args)
        func.call(context, ...args)
      },delay)
    }
  }
}
复制代码

节流(throttle)

所谓节流,就是单位时间内不管触发多少次函数,只固定执行一次函数。  节流会降低函数的执行频率。

节流我们一般用在单位时间内只需执行一次的场景,比如视频播放进度的保存、游戏里面的子弹射击、鼠标移动事件、窗口大小缩放事件、滚动条滚动事件等等,如果还有更好的场景欢迎评论区补充。

节流有定时器版本和时间戳版本。

定时器版本

function throttle1(func, delay) {
  let timer = null;
  return function () {
    const context = this;
    const args = arguments;
    if (!timer) {
      timer = setTimeout(() => {
        timer = null;
        // func.apply(context, args);
        func.call(context, ...args);
      }, delay);
    }
  };
}
复制代码

时间戳版本

function throttle2(func, delay) {
  let pre = 0;
  return function () {
    const context = this;
    const args = arguments;
    let now = Date.now();
    if (now - pre > delay) {
      pre = now;
      // func.apply(context, args);
      func.call(context, ...args);
    }
  };
}
复制代码

组合版本

function throttle3(func, delay, timestamp=true) {
  let timer = null
  let pre = 0
  return function() {
    const context = this
    const args = arguments
    if(timestamp) {
      let now = Date.now()
      if(now - pre > delay) {
        pre = now
        //func.apply(context, args)
        func.call(context, ...args)
      }
    } else {
      if(!timer) {
        timer = setTimeout(() => {
          timer = null;
          // func.apply(context, args);
          func.call(context, ...args);
        }, delay)
      }
    }
  }
}
复制代码

Vue中使用

很多小伙伴虽然知道防抖和节流,但是却不知道在Vue中如何使用节流和防抖,下面笔者介绍两种在Vue中使用防抖和节流的方法。

方法1

通过外部引入的方式。

防抖

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),
  },
};
复制代码

方法2

写在本文件里面。

防抖

  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);
    },
  },
复制代码

后记

本文为笔者个人学习笔记,如有谬误,还请告知,万分感谢!如果本文对你有所帮助,还请点个关注点个赞~,您的支持是笔者不断更新的动力!


作者:苏苏同学
链接:https://juejin.cn/post/7044818549751152647
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值