通过节流函数(throttle)解决鼠标移动太快不触发mouseleave问题

最近在做项目的过程中遇到了一个问题,就是鼠标在移动太快的时候不会触发mouseleave,会导致之前mouseenter显示的内容一直显示,最终在网上看到节流函数(throttle)就试了一下,完美解决,这里跟大家分享一下。具体什么是节流函数(throttle),网上有一大推的文章,这里就只简单的给大家介绍一下:
1.定义
规定在一个单位时间内,只能触发一次函数,如果这个单位时间内触发多次函数,只有一次生效; 典型的案例就是鼠标不断点击触发,规定在n秒内多次点击只有一次生效。

2.实现原理
其原理是用时间戳来判断是否已到回调该执行时间,记录上次执行的时间戳,然后每次触发 scroll 事件执行回调,回调中判断当前时间戳距离上次执行时间戳的间隔是否已经到达 规定时间段,如果是,则执行,并更新上次执行的时间戳

主要适用于

resize、scroll、mousemove等事件触发监听,比如我这里的mouseleave也可以用

我这个项目是用vue写的,下面直接上代码,简单粗暴,必要的地方我会有注释:
html部分:

<template>
<div @mouseenter="showList" @mouseleave="hideList">
</template>

js部分:

<script>
export default {
  data () {
    return {
      count: 0,
    hideList: () => {}
    }
  },
  created () {
   this.hideList = this.fnThrottle(this.hideListThrottle, 100);
  },
  methods: {
  	  hideListThrottle() {
        this.listShow = false;  // 这里是我的代码内容,换成自己的代码即可
      },
      /**
        ******这里是节流函数******
 		* @param {Function} fn 延时调用函数
	    * @param {Number} delay 延迟多长时间
	    * @param {Number} atleast 至少多长时间触发一次
 	    * @return {Function} 延迟执行的方法
	 */
      fnThrottle (fn, delay, atleast) {  
        let timer = null;
        let previous = null;
        return function () {
          let now = +new Date();
          if (!previous) previous = now;
          if (atleast && now - previous > atleast) {
            fn();
            previous = now;
            clearTimeout(timer)
          } else {
            clearTimeout(timer);
            timer = setTimeout(function () {
              fn();
              previous = null
            }, delay)
          }
        }
      },
      }
</script>

【注意】要把hideList函数放到data属性中,然后在created生命周期给hideList赋值,不然的话会执行多次你的那个函数(即我这里的hideListThrottle)。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
如果你封装的节流防抖函数返回后面的函数没有执行,可能是因为在封装的过程中没有正确处理函数的执行逻辑。以下是一个修复的示例: ```typescript // utils/debounce.ts export function debounce(func: Function, delay: number) { let timer: NodeJS.Timeout | null = null; return function(...args: any[]) { if (timer) { clearTimeout(timer); } timer = setTimeout(() => { func.apply(this, args); }, delay); }; } // utils/throttle.ts export function throttle(func: Function, delay: number) { let timer: NodeJS.Timeout | null = null; let lastRun = 0; return function(...args: any[]) { const currentTime = Date.now(); if (!timer) { func.apply(this, args); lastRun = currentTime; return; } if (currentTime - lastRun >= delay) { func.apply(this, args); lastRun = currentTime; } }; } ``` 在上面的示例中,修复了防抖函数节流函数的返回逻辑。 对于防抖函数,当延迟时间内再次触发时,会先清除之前的定时器,然后重新设置定时器。这样可以确保只有最后一次触发的定时器会执行回调函数。 对于节流函数,初始状态下,如果没有定时器存在,则立即执行回调函数。如果已经存在定时器,则根据当前时间与上次运行时间的差值判断是否达到节流时间间隔,如果满足条件,则执行回调函数。 请注意,以上示例是基于Node.js环境下的实现,如果你在浏览器环境中使用,请适当调整定时器的类型和清除方式。另外,确保你正确使用这些封装的函数,并传递正确的参数和回调函数
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值