防抖和节流

sunqqw / 2023-05-11 / 原文

卡顿现象

//正常情况(用户慢慢的操作):鼠标进入,每一个一级分类h3,都会触发鼠标进入事件
//非正常情况(用户操作很快):本身全部的一级分类都应该触发鼠标进入事件,但是经过测试,只有部分h3触发了
//就是由于用户行为过快,导致浏览器反应不过来。如果当前回调函数中有一些大量业务,有可能出现卡顿现象
 changeIndex(index) {
	this.cuurentIndex = index;
},
  

正常:事件触发非常频繁,而且每一次的触发,回调函数都要去执行(如果时间很短,而回调函数内部有计算,那么很可能出现浏览器卡顿)
节流:在规定的间隔时间范围内不会重复触发回调,只有大于这个时间间隔才会触发回调,把频繁触发变为少量触发
防抖:前面的所有的触发都被取消,最后一次执行在规定的时间之后才会触发,也就是说如果连续快速的触发只会执行一次
 //throttle回调函数别用箭头函数,可能出现上下文this不匹配
//lodash插件:里面封装函数的防抖与节流的业务【闭包+延迟器】
https://www.lodashjs.com/docs/lodash.debounce

//1:lodash函数库对外暴露_函数
console.log(_)
console.log(_.debounce)

防抖:用户操作很频繁,但是只是执行一次
节流:用户操作很频繁,但是把频繁的操作变为少量操作【可以给浏览器有充裕的时间解析代码】

_.debounce(func, [wait=0], [options=]) 防抖

参数

  1. func (Function): 要防抖动的函数。
  2. [wait=0] (number): 需要延迟的毫秒数。
  3. [options=] (Object): 选项对象。
  4. [options.leading=false] (boolean): 指定在延迟开始前调用。
  5. [options.maxWait] (number): 设置 func 允许被延迟的最大值。
  6. [options.trailing=true] (boolean): 指定在延迟结束后调用。

返回

(Function): 返回新的 debounced(防抖动)函数。

应用场景

  • search搜索联想,用户在不断输入值时,用防抖来节约请求资源。
  • 频繁操作点赞和取消点赞,因此需要获取最后一次操作结果并发送给服务器

实现一个简单的防抖

//用定时器实现防抖
function debounce(func,wait) {
  var timer=null;
  return function() {
    //保存当前调用的dom对象
    var _this=this;
    //保存事件对象
    var args=arguments;
    clearTimeout(timer)
    timer=setTimeout(function() {
      func.apply(_this,args)
    },wait)
  }

}

_.throttle(func, [wait=0], [options=]) 节流

参数

  1. func (Function): 要节流的函数。
  2. [wait=0] (number): 需要节流的毫秒。
  3. [options=] (Object): 选项对象。
  4. [options.leading=true] (boolean): 指定调用在节流开始前。
  5. [options.trailing=true] (boolean): 指定调用在节流结束后。

返回

(Function): 返回节流的函数。

import throttle from "lodash/throttle";

methods:{
	changeIndex: throttle(function (index) {
		this.cuurentIndex = index;
	}, 50),
}

应用场景

  • 鼠标不断点击触发,mousedown(单位时间内只触发一次)
  • window触发resize的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用防抖来让其只触发一次

实现一个简单的节流

//定时器实现节流
function throttle(func,wait) {
  var timer=null;

  return function() {
    var _this=this;
    var args=arguments;
    if(!timer) {
      timer=setTimeout(function() {
        timer=null;
        func.apply(_this,args)
      },wait)
    }
  }
}


//时间戳实现节流
function throttle(func,wait) {
  //定义初始时间
  var oldTime=0;

  return function() {
    var _this=this;
    var args=arguments;

    //当前时间戳
    var newTime=+new Date();

    //判断用当前时间减去旧的时间,如果大于wait指定的时间就会触发
    if(newTime-oldTime>wait) {
      //执行触发的函数
      func.apply(_this,args)
      //将旧时间更新
      oldTime=newTime;
    }

  }
}