React前端DOM常见Hook封装实例分析(DOM,hook,react,开发技术)

时间:2024-05-09 08:26:26 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

useEventListener

优雅的使用 addEventListener。

我们先来看看 addEventListener 的定义,以下来自 MDN 文档:

EventTarget.addEventListener() 方法将指定的监听器注册到 EventTarget 上,当该对象触发指定的事件时,指定的回调函数就会被执行。

这里的 EventTarget 可以是一个文档上的元素 Element,Document和Window 或者任何其他支持事件的对象 (比如 XMLHttpRequest)。

我们看 useEventListener 函数 TypeScript 定义,通过类型重载,它对 Element、Document、Window 等元素以及其事件名称和回调参数都做了定义。

functionuseEventListener<KextendskeyofHTMLElementEventMap>(eventName:K,handler:(ev:HTMLElementEventMap[K])=>void,options?:Options<HTMLElement>,):void;functionuseEventListener<KextendskeyofElementEventMap>(eventName:K,handler:(ev:ElementEventMap[K])=>void,options?:Options<Element>,):void;functionuseEventListener<KextendskeyofDocumentEventMap>(eventName:K,handler:(ev:DocumentEventMap[K])=>void,options?:Options<Document>,):void;functionuseEventListener<KextendskeyofWindowEventMap>(eventName:K,handler:(ev:WindowEventMap[K])=>void,options?:Options<Window>,):void;functionuseEventListener(eventName:string,handler:noop,options:Options):void;

内部代码比较简单:

  • 判断是否支持 addEventListener,支持则将参数进行传递。可以留意注释中的几个参数的作用,当做复习,这里不展开细说。

  • useEffect 的返回逻辑,也就是组件卸载的时候,会自动清除事件监听器,避免产生内存泄露。

functionuseEventListener(//事件名称eventName:string,//处理函数handler:noop,//设置options:Options={},){consthandlerRef=useLatest(handler);useEffectWithTarget(()=>{consttargetElement=getTargetElement(options.target,window);if(!targetElement?.addEventListener){return;}consteventListener=(event:Event)=>{returnhandlerRef.current(event);};//监听事件targetElement.addEventListener(eventName,eventListener,{//listener会在该类型的事件捕获阶段传播到该EventTarget时触发。capture:options.capture,//listener在添加之后最多只调用一次。如果是true,listener会在其被调用之后自动移除。once:options.once,//设置为true时,表示listener永远不会调用preventDefault()。如果listener仍然调用了这个函数,客户端将会忽略它并抛出一个控制台警告passive:options.passive,});//移除事件return()=>{targetElement.removeEventListener(eventName,eventListener,{capture:options.capture,});};},[eventName,options.capture,options.once,options.passive],options.target,);}

useClickAway

监听目标元素外的点击事件。

提到这个的应用场景,应该是模态框,点击外部阴影部分,自动关闭的场景。那这里它是怎么实现的呢?

首先它支持传递 DOM 节点或者 Ref,并且是支持数组方式。 事件默认是支持 click,开发者可以自行传递并支持数组方式。

exportdefaultfunctionuseClickAway<TextendsEvent=Event>(//触发函数onClickAway:(event:T)=>void,//DOM节点或者Ref,支持数组target:BasicTarget|BasicTarget[],//指定需要监听的事件,支持数组eventName:string|string[]='click',){}

然后内部通过 document.addEventListener 监听事件。组件卸载的时候清除事件监听。

//事件列表consteventNames=Array.isArray(eventName)?eventName:[eventName];//document.addEventListener监听事件,通过事件代理的方式知道目标节点eventNames.forEach((event)=>document.addEventListener(event,handler));return()=>{eventNames.forEach((event)=>document.removeEventListener(event,handler));};

最后看 handler 函数,通过 event.target 获取到触发事件的对象 (某个 DOM 元素) 的引用,判断假如不在传入的 target 列表中,则触发定义好的 onClickAway 函数。

consthandler=(event:any)=>{consttargets=Array.isArray(target)?target:[target];if(//判断点击的DOMTarget是否在定义的DOM元素(列表)中targets.some((item)=>{consttargetElement=getTargetElement(item);return!targetElement||targetElement.contains(event.target);})){return;}//触发点击事件onClickAwayRef.current(event);};

小结一下,useClickAway 就是使用了事件代理的方式,通过 document 监听事件,判断触发事件的 DOM 元素是否在 target 列表中,从而决定是否要触发定义好的函数。

useEventTarget

常见表单控件(通过 e.target.value 获取表单值) 的 onChange 跟 value 逻辑封装,支持自定义值转换和重置功能。

直接看代码,比较简单,其实就是监听表单的 onChange 事件,拿到值后更新 value 值,更新的逻辑支持自定义。

functionuseEventTarget<T,U=T>(options?:Options<T,U>){const{initialValue,transformer}=options||{};const[value,setValue]=useState(initialValue);//自定义转换函数consttransformerRef=useLatest(transformer);constreset=useCallback(()=>setValue(initialValue),[]);constonChange=useCallback((e:EventTarget<U>)=>{//获取e.target.value的值,并进行设置const_value=e.target.value;if(isFunction(transformerRef.current)){returnsetValue(transformerRef.current(_value));}//notransformer=>UandTshouldbethesamereturnsetValue(_valueasunknownasT);},[]);return[value,{onChange,reset,},]asconst;}

useTitle

用于设置页面标题。

这个页面标题指的是浏览器 Tab 中展示的。通过 document.title 设置。

React前端DOM常见Hook封装实例分析

代码非常简单,一看就会:

functionuseTitle(title:string,options:Options=DEFAULT_OPTIONS){consttitleRef=useRef(isBrowser?document.title:'');useEffect(()=>{document.title=title;},[title]);useUnmount(()=>{//组件卸载后,恢复上一次的titleif(options.restoreOnUnmount){document.title=titleRef.current;}});}

useFavicon

设置页面的 favicon。

favicon 指的是页面 Tab 的这个 ICON。

React前端DOM常见Hook封装实例分析

原理是通过 link 标签设置 favicon。

constuseFavicon=(href:string)=>{useEffect(()=>{if(!href)return;constcutUrl=href.split('.');constimgSuffix=cutUrl[cutUrl.length-1].toLocaleUpperCase()asImgTypes;constlink:HTMLLinkElement=document.querySelector("link[rel*='icon']")||document.createElement('link');//用于定义链接的内容的类型。link.type=ImgTypeMap[imgSuffix];//指定被链接资源的URL。link.href=href;//此属性命名链接文档与当前文档的关系。link.rel='shortcuticon';document.getElementsByTagName('head')[0].appendChild(link);},[href]);};
 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:React前端DOM常见Hook封装实例分析的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:Spring Data JPA在@Query中怎么使用投影下一篇:

36 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18