携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第18天,点击查看活动详情
💻文档地址:ahooks.js.org/zh-CN/
👨💻github地址:github.com/alibaba/hoo…
来看一张图
utils 函数
useEventListener
对 eventListener 做一个封装。
入参有三个
eventName: string: 事件名称handler: noop: 执行函数options:listener属性的可选参数对象- capture: 表示
listener会在该类型的事件捕获阶段传播到该EventTarget时触发。 - once: 表示
listener 在添加之后最多只调用一次。如果是true,listener会在其被调用之后自动移除。 - passive: 设置为 true 时,表示
listener永远不会调用preventDefault()。
- capture: 表示
useLatest(handler) 获取当前函数最新的 ref。判断当前 element 是否存在 addEventListener。监听 eventName,执行对应的函数。卸载时,移除 Listener。
function useEventListener(eventName: string, handler: noop, options: Options = {}) {
const handlerRef = useLatest(handler);
useEffectWithTarget(
() => {
const targetElement = getTargetElement(options.target, window);
if (!targetElement?.addEventListener) {
return;
}
const eventListener = (event: Event) => {
return handlerRef.current(event);
};
targetElement.addEventListener(eventName, eventListener, {
capture: options.capture,
once: options.once,
passive: options.passive,
});
return () => {
targetElement.removeEventListener(eventName, eventListener, {
capture: options.capture,
});
};
},
[eventName, options.capture, options.once, options.passive],
options.target,
);
}
useMouse
监听 mousemove 事件。
初始化数据。
const initState: CursorState = {
// 鼠标点击位置距离当前电脑屏幕X轴(左侧)的位置
screenX: NaN,
// 鼠标点击位置距离当前电脑屏幕Y轴(顶部)的位置
screenY: NaN,
// 鼠标相对于浏览器X轴(左侧)的位置
clientX: NaN,
// 鼠标相对于浏览器Y轴(顶部)的位置
clientY: NaN,
// 鼠标相对于浏览器X轴(左侧)的位置,包含页面横向滚动距离(被卷去的body部分的长度)
pageX: NaN,
// 鼠标相对于浏览器Y轴(顶部)的位置,包含页面横向滚动距离(被卷去的body部分的长度)
pageY: NaN,
elementX: NaN,
elementY: NaN,
elementH: NaN,
elementW: NaN,
elementPosX: NaN,
elementPosY: NaN,
};
useMouse 无传入 target 的时候,监听整个页面的滚动。
export default (target?: BasicTarget) => {
const [state, setState] = useRafState(initState);
useEventListener(
'mousemove',
(event: MouseEvent) => {
const { screenX, screenY, clientX, clientY, pageX, pageY } = event;
const newState = {
screenX,
screenY,
clientX,
clientY,
pageX,
pageY,
elementX: NaN,
elementY: NaN,
elementH: NaN,
elementW: NaN,
elementPosX: NaN,
elementPosY: NaN,
};
setState(newState);
},
{
target: () => document,
},
);
return state;
};
当页面传入 target。使用 Element.getBoundingClientRect() 方法返回一个 DOMRect 对象,其提供了元素的大小及其相对于视口的位置。
if (targetElement) {
const { left, top, width, height } = targetElement.getBoundingClientRect();
newState.elementPosX = left + window.pageXOffset;
newState.elementPosY = top + window.pageYOffset;
newState.elementX = pageX - newState.elementPosX;
newState.elementY = pageY - newState.elementPosY;
newState.elementW = width;
newState.elementH = height;
}
Example
import React, { useRef } from 'react';
import { useMouse } from 'ahooks';
export default () => {
const ref = useRef(null);
const { elementX, elementY, elementPosX, elementPosY, elementW, elementH } = useMouse(ref.current);
return (
<>
<div ref={ref}> element </div>
</>
);
};