【react实战】如何实现监听窗口大小变化

在日常开发场景中,监听窗口变化是一个比较常见又很重要的业务功能,其实实现起来也很简单,今天就来记录一下具体的实现以及注意事项。

实现思路

在 React 中,可以通过监听 window 的 resize 事件来检测可视区域(viewport)的宽度变化。

其中实现的关键为:

  • window.innerWidth:获取浏览器可视区域的宽度
  • window 的 resize 事件:监听窗口大小的变化,但要注意防抖,避免触发性能问题。虽然 useEffect 只执行两次,但它注册的 resize 事件回调会在每次窗口变化时触发,而这个触发频率可能极高。
  • 在组件销毁时正确清理监听器,移除 resize 事件监听,避免内存泄漏。

具体实现

js 复制代码
import React, { useEffect, useState } from 'react';

export default function ViewportWidthTracker() {
  const [width, setWidth] = useState(window.innerWidth);

  useEffect(() => {
  // 监听窗口大小变化
  let timeoutId = null;
  const handleResize = () => {
    // 每次触发 resize 时清除之前的定时器
    clearTimeout(timeoutId);
    // 设置新的定时器,延迟 150ms 执行
    timeoutId = setTimeout(() => {
      setSize({ width: window.innerWidth, height: window.innerHeight });
    }, 150);
  };

    window.addEventListener('resize', handleResize);

    // 清理监听器
    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, []); // 空依赖数组确保只在组件挂载和卸载时运行

  return (
    <div>
      <h1>当前可视区域宽度: {width}px</h1>
    </div>
  );
}

注意事项

  1. SSR 环境问题:在服务端渲染(如 Next.js)中,window 对象不存在。可通过条件判断避免错误
js 复制代码
useEffect(() => {
 if (typeof window === 'undefined') return;
 // 监听逻辑
}, []);
  1. 组件卸载时清理:必须在 componentWillUnmount 或 useEffect 返回的清理函数中移除事件监听,防止内存泄漏。

封装自定义 hook

这个场景比较常见,可以封装为自己的 hook,方便后续调用。

js 复制代码
import { useState, useEffect } from 'react';

function useWindowSize() {
  const [size, setSize] = useState({ width: 0, height: 0 });

  useEffect(() => {
  	// 监听窗口大小变化
  let timeoutId = null;
  const updateSize = () => {
    // 每次触发 resize 时清除之前的定时器
    clearTimeout(timeoutId);
    // 设置新的定时器,延迟 150ms 执行
    timeoutId = setTimeout(() => {
      setSize({ width: window.innerWidth, height: window.innerHeight });
    }, 150);
  };
    
    window.addEventListener('resize', updateSize);
    updateSize();
    
    return () => window.removeEventListener('resize', updateSize);
  }, []);

  return size;
}

// 使用自定义 Hook
function MyComponent() {
  const size = useWindowSize();
  
  return (
    <div>
      当前窗口: {size.width} x {size.height}
    </div>
  );
}
相关推荐
Ken_11151 小时前
小体积附件下载正常,大附件下载异常
javascript
变与不变8062 小时前
jQuery怎么使用
前端·javascript
神膘护体小月半2 小时前
flex 布局的 order 属性
前端·css
paopaokaka_luck2 小时前
流浪动物救助与收养系统(DeepSeek AI对话、 ECharts多维分析、救助流程衔接、领养与回访衔接、 捐赠确认与公示、志愿者协作)
java·前端·javascript·人工智能·mysql·echarts·推荐算法
仰望.2 小时前
vue 表格组件 vxe-table 树表格懒加载支持拖拽排序的详细用法
前端·javascript·vue.js·vxe-table
前端 贾公子2 小时前
vite-plugin-uni-manifest 升级指南
前端
小码哥_常2 小时前
iPhone 用户传了张 HEIC,我的前端崩了
前端
小码哥_常2 小时前
你发的原图可能暴露你家地址——聊聊图片 EXIF 隐私
前端
java1234_小锋2 小时前
【技术专题】CSS3 网页技术 - CSS3 优先级
前端·css·css3
鸿蒙开发4 小时前
共享 Schema 与 SchemaFactory
前端·后端·harmonyos