一、引言:动态布局的基石工具
在响应式Web开发中,实时感知窗口尺寸是实现自适应布局的核心需求。本文介绍的useWindowSize
自定义Hook,通过简洁的代码封装了窗口尺寸监听逻辑,为React组件提供了动态响应视口变化的能力。
二、Hook核心功能
这个轻量级工具具备以下特性:
-
📏 实时获取窗口宽度和高度
-
🔄 自动响应窗口缩放事件
-
🧹 内置事件监听清理机制
-
⚡ 开箱即用的零配置体验
三、实现原理剖析
3.1 核心代码结构
import { useState, useEffect } from 'react';
const useWindowSize = () => {
const [windowSize, setWindowSize] = useState({
width: window.innerWidth,
height: window.innerHeight,
});
const handleResize = () => {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
};
useEffect(() => {
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return windowSize;
};
3.2 关键技术点
-
状态初始化
useState({
width: window.innerWidth, // 初始宽度
height: window.innerHeight // 初始高度
})
首次渲染时同步获取窗口尺寸
-
事件绑定
useEffect(() => {
window.addEventListener('resize', handleResize);
return () => window.removeEventListener(...); // 清理函数
}, []); // 空依赖数组确保只绑定一次
-
更新触发
const handleResize = () => {
setWindowSize({...}); // 更新状态触发重新渲染
}
四、使用示例
4.1 基础用法
const ResponsiveComponent = () => {
const { width, height } = useWindowSize();
return (
<div>
<p>当前视口宽度:{width}px</p>
<p>当前视口高度:{height}px</p>
</div>
);
}
4.2 响应式布局
const AdaptiveLayout = () => {
const { width } = useWindowSize();
return (
<div style={{
flexDirection: width < 768 ? 'column' : 'row'
}}>
{/* 移动端竖排/PC端横排 */}
</div>
);
}
4.3 媒体查询替代方案
const BreakpointDemo = () => {
const { width } = useWindowSize();
return (
<>
{width >= 1200 && <DesktopView />}
{width < 1200 && width >= 768 && <TabletView />}
{width < 768 && <MobileView />}
</>
);
}
五、注意事项与最佳实践
5.1 服务端渲染(SSR)处理
// 安全初始化方案
const [windowSize, setWindowSize] = useState({
width: typeof window !== 'undefined' ? window.innerWidth : 0,
height: typeof window !== 'undefined' ? window.innerHeight : 0
});
5.2 性能优化建议
// 使用防抖函数优化高频触发
import { debounce } from 'lodash';
const handleResize = debounce(() => {
setWindowSize({...});
}, 150); // 150ms延迟
5.3 内存管理
-
确保组件卸载时自动移除监听器
-
避免在Hook外部手动操作事件监听
六、扩展方案
6.1 添加断点检测
const useBreakpoint = () => {
const { width } = useWindowSize();
return {
isMobile: width < 768,
isTablet: width >= 768 && width < 1200,
isDesktop: width >= 1200
};
}
6.2 支持自定义目标元素
const useElementSize = (elementRef) => {
const [size, setSize] = useState({...});
useEffect(() => {
const observer = new ResizeObserver(entries => {
setSize({
width: entries[0].contentRect.width,
height: entries[0].contentRect.height
});
});
if(elementRef.current) observer.observe(elementRef.current);
return () => observer.disconnect();
}, []);
return size;
}
七、总结与展望
这个useWindowSize
自定义Hook通过简洁的实现,解决了响应式开发中的关键痛点。相比CSS媒体查询,它具备以下优势:
✅ 支持动态逻辑判断
✅ 可直接在渲染逻辑中使用
✅ 提供精确的像素数值
✅ 便于实现复杂交互
未来可扩展方向:
-
添加方向变化检测(横屏/竖屏)
-
集成设备类型推断
-
支持iframe内尺寸监测
-
添加TypeScript类型定义
建议在项目中根据具体需求进行适当扩展,同时注意SSR场景的兼容性和性能优化,打造更完善的响应式开发工具链。