源码解读

useEventListener:事件监听

主要逻辑就是,useEffect addEventListener 注册事件,return 的时候 removeEventListener

useClickAway:监听目标元素外的点击时间

Node.contains() 返回一个布尔值,来表示传入的节点是否为该节点的后代节点,主要用这个 API 来判断是不是点击到了某个元素的内部
https://developer.mozilla.org/zh-CN/docs/Web/API/Node/contains

  1. export default function useClickAway<T extends Event = Event>(
  2. onClickAway: (event: T) => void,
  3. target: BasicTarget | BasicTarget[],
  4. eventName: string = 'click',
  5. ) {
  6. const onClickAwayRef = useLatest(onClickAway);
  7. useEffectWithTarget(
  8. () => {
  9. const handler = (event: any) => {
  10. const targets = Array.isArray(target) ? target : [target];
  11. // 使用 some,有一个满足了,说明就是点击内部了,直接 return 不执行 callback
  12. if (
  13. targets.some((item) => {
  14. const targetElement = getTargetElement(item);
  15. // 这里用 contains 判断是否点击到内部
  16. return !targetElement || targetElement?.contains(event.target);
  17. })
  18. ) {
  19. return;
  20. }
  21. onClickAwayRef.current(event);
  22. };
  23. document.addEventListener(eventName, handler);
  24. return () => {
  25. document.removeEventListener(eventName, handler);
  26. };
  27. },
  28. [eventName],
  29. target,
  30. );
  31. }

useDocumentVisibility:监听当前页面是否可见

主要使用 document.visibilityState 属性,返回当前 document 的可见性:https://developer.mozilla.org/zh-CN/docs/Web/API/Document/visibilityState,同时可以监听 visibilitychange 事件

  1. type VisibilityState = 'hidden' | 'visible' | 'prerender' | undefined;
  2. const getVisibility = () => {
  3. if (!isBrowser) {
  4. return 'visible';
  5. }
  6. return document.visibilityState;
  7. };
  8. function useDocumentVisibility(): VisibilityState {
  9. // 获取初始值
  10. const [documentVisibility, setDocumentVisibility] = useState(() => getVisibility());
  11. // 监听事件
  12. useEventListener(
  13. 'visibilitychange',
  14. () => {
  15. setDocumentVisibility(getVisibility());
  16. },
  17. {
  18. target: () => document,
  19. },
  20. );
  21. return documentVisibility;
  22. }

useDrop

useDrag

useTitle:设置页面标题

  1. import { useEffect, useRef } from 'react';
  2. import useUnmount from '../useUnmount';
  3. import isBrowser from '../utils/isBrowser';
  4. export interface Options {
  5. restoreOnUnmount?: boolean;
  6. }
  7. const DEFAULT_OPTIONS: Options = {
  8. restoreOnUnmount: false,
  9. };
  10. function useTitle(title: string, options: Options = DEFAULT_OPTIONS) {
  11. const titleRef = useRef(isBrowser ? document.title : '');
  12. useEffect(() => {
  13. document.title = title;
  14. }, [title]);
  15. // 组件卸载时,返回上一个页面标题
  16. useUnmount(() => {
  17. if (options.restoreOnUnmount) {
  18. document.title = titleRef.current;
  19. }
  20. });
  21. }
  22. export default useTitle;