首页 > 其他分享 >自定义hook - 双击事件 - useDBClick

自定义hook - 双击事件 - useDBClick

时间:2023-05-25 11:23:48浏览次数:42  
标签:const 自定义 interval current hook return ref 双击

1. 问题:

  业务场景中同时需要单击、双击事件,但是原生的onDoubleClick触发双击的时候会同时触发单击事件;

2.解决方案:

  封装一个自定义hook能独立地触发单击和双击事件;

  根据两次点击的间隔是否小于 interval 来判断触发单击双击事件;

// useDBClick.ts
import { MutableRefObject, useEffect, useRef, MouseEvent as RMouseEvent } from 'react'; export interface UseDBClickOptions<T extends HTMLElement> { ref: MutableRefObject<T | undefined | null> | T; onClick?: (e: RMouseEvent<T>) => void; onDBClick?: (e: RMouseEvent<T>) => void; /** * 单位 ms */ interval?: number; } /** * * eg: * useDBClick({ * ref, * onClick: () => {}, * onDBClick: () => {}, * interval: 200 * }); * */ const useDBClick = <T extends HTMLElement = HTMLElement>(options: UseDBClickOptions<T>) => { const { ref, onClick, onDBClick, interval = 200 } = options; if (typeof interval !== 'number' || isNaN(interval)) { throw new Error('Invalid interval type'); } const intervalRef = useRef<number | null>(); const timerRef = useRef<NodeJS.Timeout | null>(); const isDom = (node: any): node is HTMLElement | SVGElement => node instanceof HTMLElement || node instanceof SVGElement; const isRefObject = (obj: any): obj is MutableRefObject<T> => 'current' in obj; const generateElement = (ref: UseDBClickOptions<T>['ref']) => { if (isRefObject(ref)) { if (isDom(ref.current)) { return ref.current; } } if (isDom(ref)) { return ref; } return; };
/**
  * 根据两次点击的间隔是否小于 interval 来判断触发单击双击事件
  */ const innerClick = (e: MouseEvent) => { const time = Date.now(); if (typeof intervalRef.current === 'number' && time - intervalRef.current < interval) { // dbclick if (timerRef.current) { clearTimeout(timerRef.current); } timerRef.current = null; intervalRef.current = null; onDBClick?.(e as unknown as RMouseEvent<T>); return; } // click intervalRef.current = time; timerRef.current = setTimeout(() => { onClick?.(e as unknown as RMouseEvent<T>); }, interval); return; }; const listenClick = () => { const element = generateElement(ref); if (!element) { return; } element.addEventListener('click', innerClick); }; const unlistenClick = () => { const element = generateElement(ref); if (!element) { return; } element.removeEventListener('click', innerClick); }; useEffect(() => { listenClick(); return () => { unlistenClick(); }; }, []); }; export default useDBClick;

 

标签:const,自定义,interval,current,hook,return,ref,双击
From: https://www.cnblogs.com/iwannadoflex/p/17426858.html

相关文章

  • 多线程合集(三)---异步的那些事之自定义AsyncTaskMethodBuilder
    引言之前在上一篇文章中多线程合集(二)---异步的那些事,async和await原理抛析,我们从源码去分析了async和await如何运行,以及将编译后的IL代码写成了c#代码,以及实现自定义的Awaiter,自定义异步状态机同时将本系列的第一篇文章的自定义TaskScheduler和自定义的Awaiter......
  • Jenkins 自定义变量
    方法一、在构建步骤中,用Windows命令设置变量,然后写入到一份文档,给其他task调用 方法二、在构建环境里,“Injectenvironmentvariablestothebuildprocess”读取或直接定义变量。读取的话可以读取上一个方法输出的变量文件 方法三、在系统配置,设置的变量属于全局变量......
  • 【Redis】自定义RedisTemplate模板,拿来直接使用
    以下是自定义RedisTemplate固定模板,拿来可以直接使用:packagecom.iot.back.message.process.config;importcom.fasterxml.jackson.annotation.JsonAutoDetect;importcom.fasterxml.jackson.annotation.PropertyAccessor;importcom.fasterxml.jackson.databind.ObjectMappe......
  • gitlab--内置的环境变量、自定义环境变量
    自定义环境变量gitlab给我们内置了很多的变量,但有时候满足不了我们的需求,例如我们需要往某个私有仓库推送镜像,需要账号和密码进行登录。这时候我们不想把密码写在.gitlab-ci.yml文件里面。我们就可以自定义一个环境变量来使用了。先来定义一个变量,设置-》CI/CD-》变量在.g......
  • mybatis关于自定义映射的使用方法
    在MyBatis中,可以通过SQL映射文件来自定义映射,即将一个查询结果映射成一个Java对象。在映射中,我们可以控制如何从查询结果中提取数据,并将其映射到Java对象的属性中。以下是一些常用的自定义映射方式:resultMap:使用resultMap元素来定义映射规则,可以精确地将查询结果映......
  • vs2019打包程序时添加自定义的系统必备组件
     若要创建引导程序包,必须创建产品清单产品清单 product.xml包清单 package.xml 将文件复制到引导程序文件夹位置C:\ProgramFiles(x86)\MicrosoftVisualStudio14.0\SDK\Bootstrapper\Packages文件夹下    ......
  • 自定义注解实现数据序列化时进行数据脱敏(基于springboot默认jackjson)、消息转换器
    消息转换器fastjson与jackjson问题在springboot中使用fastjson的@jsonField无效原因:在springboot默认有json(jackjson)解析工具,所以使用fastjson不会生效解决方案替换默认的解析工具(笔者不推荐,这里根据自己项目决定)fastjson替换默认的jackjson第一种方法bean方法packagecom......
  • Visual Studio Code (vscode)自定义用户代码段快速打出for循环等
    比如fori这样的快捷键就打不出代码块了自定义用户代码块的方法:工具栏>文件>首选项>用户代码片段  然后在弹出的搜索框中填写javascript.json有提示不用打全就行(会有javascript选中)  打开配置文件javascript.json这里面显示的就是编写代码块的例子"P......
  • 界面控件DevExtreme使用指南 - 如何自定义上下文菜单和工具栏
    DevExtreme FileManager(文件管理器)小部件现在支持自定义内置的工具栏和上下文菜单,用户可以使用标准和定义的命令项填充项目集合,并配置设置来更改其外观和操作。DevExtreme拥有高性能的HTML5/JavaScript小部件集合,使您可以利用现代Web开发堆栈(包括React,Angular,ASP.NETCore,jQu......
  • 控件包含代码块(即 <% ... %>),因此无法修改控件集合(用户自定义控件中)
    https://www.cnblogs.com/zlfucku/archive/2011/09/05/2167943.html原因:就是runat中不能有<%%>这样的东西,不然就会报这个错误解决办法: 这两行拖到body里就好了,不要放在有headrunat=server的代码块内,不然就报这个错。......