ahooks源码分析-useMouse

203 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第11天,点击查看活动详情

今天开始一起学习分享 ahooks 的源码

ahooks是阿里巴巴出品的一套高质量可靠的 React Hooks 库

今天分享 第11个 hooks-useMouse

useBoolean

首先看下 useMouse 的作用是什么

useMouse 的作用是监听鼠标位置

接下来 看下 API

API

const state: {
  screenX: number,
  screenY: number,
  clientX: number,
  clientY: number,
  pageX: number,
  pageY: number,
  elementX: number,
  elementY: number,
  elementH: number,
  elementW: number,
  elementPosX: number,
  elementPosY: number,
} = useMouse(target?: Target);

Params

参数只有1个,target表示 目标元素dom节点 或者 也可以传入 ref来表示目标元素

参数说明类型
targetDOM 节点或者 RefElement | () => Element | MutableRefObject<Element>

Result

返回的结果 是 各种 距离

参数说明类型
screenX距离显示器左侧的距离number
screenY距离显示器顶部的距离number
clientX距离当前视窗左侧的距离number
clientY距离当前视窗顶部的距离number
pageX距离完整页面左侧的距离number
pageY距离完整页面顶部的距离number
elementX距离指定元素左侧的距离number
elementY距离指定元素顶部的距离number
elementH指定元素的高number
elementW指定元素的宽number
elementPosX指定元素距离完整页面左侧的距离number
elementPosY指定元素距离完整页面顶部的距离number

接下来 看下 用法

基本用法

获取鼠标位置。

只有使用useMouse,返回mouse,mouse就能返回鼠标的当前位置

import { useMouse } from 'ahooks';
import React from 'react';

export default () => {
  const mouse = useMouse();

  return (
    <div>
      <p>
        Client - x: {mouse.clientX}, y: {mouse.clientY}
      </p>
      <p>
        Page - x: {mouse.pageX}, y: {mouse.pageY}
      </p>
      <p>
        Screen - x: {mouse.screenX}, y: {mouse.screenY}
      </p>
    </div>
  );
};

image.png

获取鼠标相对于元素的位置

通过传入目标元素,可以获取鼠标相对于元素的位置。

import React, { useRef } from 'react';
import { useMouse } from 'ahooks';

export default () => {
  const ref = useRef(null);
  const mouse = useMouse(ref.current);

  return (
    <>
      <div
        ref={ref}
        style={{
          width: '200px',
          height: '200px',
          backgroundColor: 'gray',
          color: 'white',
          lineHeight: '200px',
          textAlign: 'center',
        }}
      >
        element
      </div>
      <div>
        <p>
          Mouse In Element - x: {mouse.elementX}, y: {mouse.elementY}
        </p>
        <p>
          Element Position - x: {mouse.elementPosX}, y: {mouse.elementPosY}
        </p>
        <p>
          Element Dimensions - width: {mouse.elementW}, height: {mouse.elementH}
        </p>
      </div>
    </>
  );
};

image.png

接下来一起看下 源码

源码

1.首先 定义 目标元素的类型

import type { BasicTarget } from '../utils/domTarget';

export type BasicTarget<T extends TargetType = Element> =
  | (() => TargetValue<T>)
  | TargetValue<T>
  | MutableRefObject<TargetValue<T>>;
  
  target?: BasicTarget

2.通过state初始化元素位置信息

const [state, setState] = useRafState(initState);

const initState: CursorState = {
  screenX: NaN,
  screenY: NaN,
  clientX: NaN,
  clientY: NaN,
  pageX: NaN,
  pageY: NaN,
  elementX: NaN,
  elementY: NaN,
  elementH: NaN,
  elementW: NaN,
  elementPosX: NaN,
  elementPosY: NaN,
};

3.使用useEventListener hooks来监听鼠标移动事件mousemove。通过event来获取元素的各位置信息,然后获取目标元素,判断如果当目标元素存在的时候,则将这些位置信息通过setState更新,最后返回state

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,
      };
      const targetElement = getTargetElement(target);
      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;
      }
      setState(newState);
    },
    {
      target: () => document,
    },
  );

其他hooks

useLatest

useEventListener

useClickAway

useDocumentVisibility

useTitle