源码解读
useEventListener:事件监听
主要逻辑就是,useEffect addEventListener 注册事件,return 的时候 removeEventListener
useClickAway:监听目标元素外的点击时间
Node.contains() 返回一个布尔值,来表示传入的节点是否为该节点的后代节点,主要用这个 API 来判断是不是点击到了某个元素的内部
https://developer.mozilla.org/zh-CN/docs/Web/API/Node/contains
export default function useClickAway<T extends Event = Event>(
onClickAway: (event: T) => void,
target: BasicTarget | BasicTarget[],
eventName: string = 'click',
) {
const onClickAwayRef = useLatest(onClickAway);
useEffectWithTarget(
() => {
const handler = (event: any) => {
const targets = Array.isArray(target) ? target : [target];
// 使用 some,有一个满足了,说明就是点击内部了,直接 return 不执行 callback
if (
targets.some((item) => {
const targetElement = getTargetElement(item);
// 这里用 contains 判断是否点击到内部
return !targetElement || targetElement?.contains(event.target);
})
) {
return;
}
onClickAwayRef.current(event);
};
document.addEventListener(eventName, handler);
return () => {
document.removeEventListener(eventName, handler);
};
},
[eventName],
target,
);
}
useDocumentVisibility:监听当前页面是否可见
主要使用 document.visibilityState 属性,返回当前 document 的可见性:https://developer.mozilla.org/zh-CN/docs/Web/API/Document/visibilityState,同时可以监听 visibilitychange 事件
type VisibilityState = 'hidden' | 'visible' | 'prerender' | undefined;
const getVisibility = () => {
if (!isBrowser) {
return 'visible';
}
return document.visibilityState;
};
function useDocumentVisibility(): VisibilityState {
// 获取初始值
const [documentVisibility, setDocumentVisibility] = useState(() => getVisibility());
// 监听事件
useEventListener(
'visibilitychange',
() => {
setDocumentVisibility(getVisibility());
},
{
target: () => document,
},
);
return documentVisibility;
}
useDrop
useDrag
useTitle:设置页面标题
import { useEffect, useRef } from 'react';
import useUnmount from '../useUnmount';
import isBrowser from '../utils/isBrowser';
export interface Options {
restoreOnUnmount?: boolean;
}
const DEFAULT_OPTIONS: Options = {
restoreOnUnmount: false,
};
function useTitle(title: string, options: Options = DEFAULT_OPTIONS) {
const titleRef = useRef(isBrowser ? document.title : '');
useEffect(() => {
document.title = title;
}, [title]);
// 组件卸载时,返回上一个页面标题
useUnmount(() => {
if (options.restoreOnUnmount) {
document.title = titleRef.current;
}
});
}
export default useTitle;