当前位置:   article > 正文

【解读 ahooks 源码系列】DOM篇(一)_ahooks源码下载

ahooks源码下载

useEventListener

优雅的使用 addEventListener。

用法

  1. import React, { useState, useRef } from 'react';
  2. import { useEventListener } from 'ahooks';
  3. export default () => {
  4. const [value, setValue] = useState(0);
  5. const ref = useRef(null);
  6. useEventListener(
  7. 'click',
  8. () => {
  9. setValue(value + 1);
  10. },
  11. { target: ref },
  12. );
  13. return (
  14. <button ref={ref} type="button">
  15. You click {value} times
  16. </button>
  17. );
  18. };
  19. 复制代码

使用场景

通用事件监听 Hook,简化写法(无需在 useEffect 卸载函数中手动移除监听函数,由内部去移除)

实现思路

  1. 判断是否支持 addEventListener
  2. 在单独只有 useEffect 实现事件监听移除的基础上,将相关参数都由外部传入,并添加到依赖项
  3. 处理事件参数的 TS 类型,addEventListener 的第三个参数也需要由外部传入

核心实现

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

EventTarget 指任何其他支持事件的对象/元素 HTMLElement | Element | Document | Window

符合 EventTarget 接口的都具有下列三个方法

  1. EventTarget.addEventListener()
  2. EventTarget.removeEventListener()
  3. EventTarget.dispatchEvent()
  4. 复制代码
  • TS 函数重载

函数重载指使用相同名称和不同参数数量或类型创建多个方法,让我们定义以多种方式调用的函数。在 TS 中为同一个函数提供多个函数类型定义来进行函数重载

  1. function useEventListener<K extends keyof HTMLElementEventMap>(
  2. eventName: K,
  3. handler: (ev: HTMLElementEventMap[K]) => void,
  4. options?: Options<HTMLElement>,
  5. ): void;
  6. function useEventListener<K extends keyof ElementEventMap>(
  7. eventName: K,
  8. handler: (ev: ElementEventMap[K]) => void,
  9. options?: Options<Element>,
  10. ): void;
  11. function useEventListener<K extends keyof DocumentEventMap>(
  12. eventName: K,
  13. handler: (ev: DocumentEventMap[K]) => void,
  14. options?: Options<Document>,
  15. ): void;
  16. function useEventListener<K extends keyof WindowEventMap>(
  17. eventName: K,
  18. handler: (ev: WindowEventMap[K]) => void,
  19. options?: Options<Window>,
  20. ): void;
  21. 复制代码

实现:

  1. function useEventListener(eventName: string, handler: noop, options: Options = {}) {
  2. const handlerRef = useLatest(handler);
  3. useEffectWithTarget(
  4. () => {
  5. const targetElement = getTargetElement(options.target, window);
  6. if (!targetElement?.addEventListener) {
  7. return;
  8. }
  9. const eventListener = (event: Event) => {
  10. return handlerRef.current(event);
  11. };
  12. // 添加监听事件
  13. targetElement.addEventListener(eventName, eventListener, {
  14. // true 表示事件在捕获阶段执行,false(默认) 表示事件在冒泡阶段执行
  15. capture: options.capture,
  16. // true 表示事件在触发一次后移除,默认 false
  17. once: options.once,
  18. // true 表示 listener 永远不会调用 preventDefault()。如果 listener 仍然调用了这个函数,客户端将会忽略它并抛出一个控制台警告
  19. passive: options.passive,
  20. });
  21. // 移除监听事件
  22. return () => {
  23. targetElement.removeEventListener(eventName, eventListener, {
  24. capture: options.capture,
  25. });
  26. };
  27. },
  28. [eventName, options.capture, options.once, options.passive],
  29. options.target,
  30. );
  31. }
  32. 复制代码

完整源码

useClickAway

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

  1. type Target = Element | (() => Element) | React.MutableRefObject<Element>;
  2. /**
  3. * 监听目标元素外的点击事件。
  4. * @param onClickAway 触发函数
  5. * @param target DOM 节点或者 Ref,支持数组
  6. * @param eventName DOM 节点或者 Ref,支持数组,默认事件是 click
  7. */
  8. useClickAway<T extends Event = Event>(
  9. onClickAway: (event: T) => void,
  10. target: Target | Target[],
  11. eventName?: string | string[]
  12. );
  13. 复制代码

用法

  1. import React, { useState, useRef } from 'react';
  2. import { useClickAway } from 'ahooks';
  3. export default () => {
  4. const [counter, setCounter] = useState(0);
  5. const ref = useRef<HTMLButtonElement>(null);
  6. useClickAway(() => {
  7. setCounter((s) => s + 1);
  8. }, ref);
  9. return (
  10. <div>
  11. <button ref={ref} type="button">
  12. box
  13. </b
声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号