持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情
今天开始一起学习分享 ahooks 的源码
ahooks是阿里巴巴出品的一套高质量可靠的 React Hooks 库
今天分享 第2个 hooks- useEventListener
useEventListener
首先看下 useEventListener 的作用是什么
useEventListener的作用是优雅的使用 JavaScript中的 addEventListener。
接下来 看下 API
API
useEventListener(
eventName: string,
handler: (ev: Event) => void,
options?: Options,
);
Params
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
eventName | 事件名称 | string | - |
handler | 处理函数 | (ev: Event) => void | - |
options | 设置(可选) | Options | - |
一共有3个参数
eventName:事件名称
handler: 事件函数
options:可选的参数
再看下 可选的 参数
Options
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
target | DOM 节点或者 ref | (() => Element) | Element | React.MutableRefObject<Element> | Window | Document | window |
capture | 可选项,listener 会在该类型的事件捕获阶段传播到该 EventTarget 时触发。 | boolean | false |
once | 可选项,listener 在添加之后最多只调用一次。如果是 true,listener 会在其被调用之后自动移除。 | boolean | false |
passive | 可选项,设置为 true 时,表示 listener 永远不会调用 preventDefault() 。如果 listener 仍然调用了这个函数,客户端将会忽略它并抛出一个控制台警告。 | boolean | false |
接下来 看下 用法
基本用法
当点击的时候 数字 加 1
import React, { useState, useRef } from 'react';
import { useEventListener } from 'ahooks';
export default () => {
const [value, setValue] = useState(0);
const ref = useRef(null);
useEventListener(
'click',
() => {
setValue(value + 1);
},
{ target: ref },
);
return (
<button ref={ref} type="button">
You click {value} times
</button>
);
};
监听 keydown 事件
监听 键盘 事件
import React, { useState } from 'react';
import { useEventListener } from 'ahooks';
export default () => {
const [value, setValue] = useState('');
useEventListener('keydown', (ev) => {
setValue(ev.code);
});
return <p>Your press key is {value}</p>;
};
接下来 看下 源码
源码
首先看下接口参数的定义
type Options<T extends Target = Target> = {
target?: T;
capture?: boolean;
once?: boolean;
passive?: boolean;
};
第一个是target,是可选的,接口定义是Target,接着再看下 Target的定义
export type Target = BasicTarget<HTMLElement | Element | Window | Document>;
这里定义了 target 可能是 上面这几种类型
另外3个参数都是可选的布尔值
capture?: boolean;
once?: boolean;
passive?: boolean;
接着 按照 target各种值的类型,使用多态编写 各种情形
function useEventListener<K extends keyof HTMLElementEventMap>(
eventName: K,
handler: (ev: HTMLElementEventMap[K]) => void,
options?: Options<HTMLElement>,
): void;
function useEventListener<K extends keyof ElementEventMap>(
eventName: K,
handler: (ev: ElementEventMap[K]) => void,
options?: Options<Element>,
): void;
function useEventListener<K extends keyof DocumentEventMap>(
eventName: K,
handler: (ev: DocumentEventMap[K]) => void,
options?: Options<Document>,
): void;
function useEventListener<K extends keyof WindowEventMap>(
eventName: K,
handler: (ev: WindowEventMap[K]) => void,
options?: Options<Window>,
): void;
function useEventListener(eventName: string, handler: noop, options: Options): void;
最后使用一个来编写逻辑
首先使用 useLatest Hooks 将 传入的 函数 包装起来,返回最新的handler
const handlerRef = useLatest(handler);
然后将 传入的 target 作为参数 传入getTargetElement方法中,最后返回目标dom
const targetElement = getTargetElement(options.target, window);
if (!targetElement?.addEventListener) {
return;
}
监听的事件函数 通过 handlerRef 来返回
const eventListener = (event: Event) => {
return handlerRef.current(event);
};
最后利用 js中提供的addEventListener和removeEventListener来监听事件函数和销毁事件函数
targetElement.addEventListener(eventName, eventListener, {
capture: options.capture,
once: options.once,
passive: options.passive,
});
return () => {
targetElement.removeEventListener(eventName, eventListener, {
capture: options.capture,
});
};