| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 |
- import { useEffect, useState } from 'react';
- /**
- * 订阅 body 的宽高,在 window resize 时更新。
- * @returns 当前 body 的 { width, height }(clientWidth/clientHeight)
- */
- export const useScreenSize = () => {
- const [screenSize, setScreenSize] = useState<{ width: number; height: number }>({
- width: 0,
- height: 0,
- });
- useEffect(() => {
- const handleResize = () => {
- const body = document.getElementsByTagName('body')[0];
- setScreenSize({ width: body?.clientWidth ?? 0, height: body?.clientHeight ?? 0 });
- };
- handleResize();
- window.addEventListener('resize', handleResize);
- return () => window.removeEventListener('resize', handleResize);
- }, []);
- return screenSize;
- };
- /**
- * 订阅 ref 对应 DOM 元素的尺寸,使用 ResizeObserver 在尺寸变化时更新。
- * @param ref 目标元素的 RefObject
- * @returns 当前元素的 { width, height }(contentRect)
- */
- export const useRefSize = <T extends HTMLElement = HTMLDivElement>(
- ref: React.RefObject<T>
- ) => {
- const [size, setSize] = useState<{ width: number; height: number }>({ width: 0, height: 0 });
- useEffect(() => {
- const element = ref.current;
- if (!element) return;
- setSize({
- width: element.clientWidth,
- height: element.clientHeight,
- });
- const resizeObserver = new ResizeObserver((entries) => {
- for (const entry of entries) {
- const { width, height } = entry.contentRect;
- setSize({ width, height });
- }
- });
- resizeObserver.observe(element);
- return () => {
- resizeObserver.disconnect();
- };
- }, [ref]);
- return size;
- };
- const MOBILE_BREAKPOINT = 768;
- const PHONE_BREAKPOINT = 640;
- /**
- * 响应式检测:基于 useScreenSize 的 body 宽度判断设备类型。
- * - isMobile: 宽度 ≤ 768px(手机 + 平板)
- * - isPhone: 宽度 < 640px(仅手机,对应 Tailwind sm 断点以下)
- */
- export function useResponsive() {
- const { width } = useScreenSize();
- return {
- isMobile: width <= MOBILE_BREAKPOINT,
- isPhone: width > 0 && width < PHONE_BREAKPOINT,
- };
- }
|