javascript实现防抖与节流

JS实现节流与防抖

1. 防抖

定义:在触发事件后,规定的事件内回调函数只能执行一次,如果在规定事件内又触发了该事件,则会重新开始计算规定事件

1.1 非立即执行版

事件触发 ->延时->执行回调函数。如果在延时中继续触发事件,则会重新进行延时。在延时结束后执行回调

代码及思路

function debounce(fn, delay) {
    let timer = null;
    return function() {
        // 清除已存在的定时器
        timer && clearTimeout(timer)
        
        timer = setTimeout(() =>{//箭头函数里的this与return函数里的this一致,都是button按钮
            fn.apply(this,arguments)
            }, delay)
        /*
        如果使用的是普通函数,需要先使用变量保存return函数里的this,再指向它。
        let that = this
        timer = setTimeout(function(){
			fn.apply(that,arguments)
			}, delay)
		*/
    }
}
1.2 立即执行版

事件触发->执行回调函数->延时。如果在延时中继续触发事件,则会重新进行延时。在延时结束后不会执行回调

代码及思路

function debounce(fn, delay,immediately) {
    let timer = null;
    return function() {
    // 清除已存在的定时器
    timer && clearTimeout(timer)

    if(immediately){ //根据immediately的值来确定是否立即执行
        if(!timer){ //如果定时器不存在时,执行回调
        	fn.apply(this,arguments)
        }
        //不管上一个延时是否完成,都需要重置定时器
        timer = setTimeout(() =>{
        	timer = null
        }, delay)

    }else{
        timer = setTimeout(() =>{
        	fn.apply(this,arguments)
        }, delay)
        }
    }
}

2. 节流

定义:在规定时间件内只能执行一次回调函数,如果在规定时间内又触发了该事件,则什么也不做

2.1 时间戳版

代码及思路

function throttle(fn, delay) {
    // 记录上次触发的时间戳
    let lastTime = 0;
    return function() {
        // 记录当前触发的时间戳
        let nowTime = Date.now();
        // 如果当前触发与上次触发的时间差值 大于 设置的周期则允许执行
        if (nowTime - lastTime > delay) {
            fn.apply(this,arguments);
            // 更新时间戳
            lastTime = nowTime;
    	}
	}
}
2.2 定时器版

代码及思路

function throttle(fn, delay){
    let timer = null;
    return function(){
        if(!timer){ //如果定时器为空,执行回调,规定时间内不再执行
            fn.apply(this.arguments)
            timer = setTimeout(()=>{
                timer = null; //延时结束后,timer置为空
            },delay)
        }
    }
}

3.防抖与节流的区别

  • 防抖是将多次执行变为最后一次执行
  • 节流是将多次执行变为在规定时间内只执行一次

4. 其他方法

除去自己封装防抖和节流函数外,还有许多JavaScript库已经为我们封装好了,这里介绍Loadsh

Lodash 是一个一致性、模块化、高性能的 JavaScript 实用工具库。

Lodash中文文档
4.1 _.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): 指定在延迟结束后调用。
4.2 _.throttle

_.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): 指定调用在节流结束后。
4.3 使用方法

在HTML使用

<html>
	<head>
		<meta charset="utf-8">
		<style>
		</style>
		<title></title>
	</head>
	<body>
	<button>submit</button>	
	<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
	<script type="text/javascript">
		function coloring (){
            let r  = Math.floor(Math.random()*255)
            let g  = Math.floor(Math.random()*255)
            let b  = Math.floor(Math.random()*255)
            document.body.style.backgroundColor = `rgb(${r},${g},${b})`
		}
		
		let btn = document.querySelector("button")
		btn.addEventListener('click',_.debounce(coloring,1000,{
			leading: true,
			trailing: false
		}))
		
		window.addEventListener('resize',_.throttle(coloring,1000))			   

	</script>
	</body>
</html>

在vue中使用

npm i --save lodash

<template>
  <div>
    <button @click="debounce">click</button>
  </div>
</template>

<script>
import _ from "lodash";
export default {
  name: "Father",
  methods: {
    debounce: _.debounce(
      function () { //这里如果使用箭头函数,this指向undefined
        this.coloring();//这里的this指向的就是vue实例
      },
      2000,
      {
        leading: true,
        trailing: false,
      }
    ),

    coloring() {
      let r = Math.floor(Math.random() * 255);
      let g = Math.floor(Math.random() * 255);
      let b = Math.floor(Math.random() * 255);
      document.body.style.backgroundColor = `rgb(${r},${g},${b})`;
    },
  },
  created() {
  	window.addEventListener("resize", _.throttle(this.coloring, 2000));
  },

};
</script>

<style lang="less" scoped>
</style>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值