ahooks源码学习之useMouse & useClickAway & useSyncState

816 阅读1分钟

useMouse

简介

useMouse 这个 hook 的作用是可以监听鼠标位置。
借用了lodash的throttle函数实现了节流。

源码实现

 const initState = {
    screenX: NaN,
    screenY: NaN,
    clientX: NaN,
    clientY: NaN,
    pageX: NaN,
    pageY: NaN
  }
  export const useMouse = () => {
    const [state, setState] = useState(initState)
    const moveFun = useCallback((state) => {
      setState(state)
    }, [])
    const debounceFn = useCallback(
      _.throttle(moveFun, 250, {
        leading: false,
        trailing: true
      }),
      [changeFun]
    )
    useEffect(() => {
      const handler = (event) => {
        const { screenX, screenY, clientX, clientY, pageX, pageY } = event
        const newState = {
          screenX,
          screenY,
          clientX,
          clientY,
          pageX,
          pageY
        }
        debounceFn(newState)
      }
      window.addEventListener('mousemove', handler)
      return () => window.removeEventListener('mousemove', handler)
    }, [])
    return state
  }

如何使用

 // 直接使用
const mouse = useMouse()

useClickAway

简介

useClickAway 这个 hook 的作用是可以监听目标元素外的点击事件。
主要使用了原生apicontains判断点击元素是否被包含在指定元素中。

源码实现

const useClickAway = (fn, dom, eventName = 'click') => {
    useEffect(() => {
      const handler = (event) => {
        // 先判断传入的dom对象是否为多个
        const doms = Array.isArray(dom) ? dom : [dom]
        // 如果点击的对象在传入的dom对象中,直接返回,不执行函数
        if (doms.some((dom) => dom.current.contains(event.target))) {
          return
        }
        fn(event)
      }
      const eventNames = Array.isArray(eventName) ? eventName : [eventName]
      eventNames.forEach((eventName) =>
        window.addEventListener(eventName, handler)
      )
      return () =>
        eventNames.forEach((eventName) =>
          window.removeEventListener(eventName, handler)
        )
    }, [])
  }

如何使用

 // 直接使用
 useClickAway(() => {
    console.log('1111')
  }, ref)
// 其他监听任意鼠标事件
  useClickAway(() => {
    console.log('1111')
  }, ref, 'mousemove')
// 监听多个元素外的`点击`事件
  useClickAway(() => {
    console.log('1111')
  }, [ref1,ref2])

useSyncState

简介

useSyncState 这个 hook 的作用是可以获取useState的最新值。
主要是useRefuseState的结合使用

源码实现

 export const useSyncState = <T>(
  initState?: T
): [{ current: T }, (data: T) => void] => {
  const [state, setStateValue] = useState<T>(initState as T)
  const stateRef = useRef<T>(state)
  const setState = (value: T) => {
    stateRef.current = value
    setStateValue(value)
  }

  return [stateRef, setState]
}

如何使用

 // 直接使用
const [state,setState] = useSyncState<string>('')
setState('2')
console.log('state.current',state.current) // 2