【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>
  );
}
相关推荐
Z兽兽5 小时前
React@18+Vite项目配置env文件
前端·react.js·前端框架
SuniaWang5 小时前
《Spring AI + 大模型全栈实战》学习手册系列 · 专题六:《Vue3 前端开发实战:打造企业级 RAG 问答界面》
java·前端·人工智能·spring boot·后端·spring·架构
A_nanda6 小时前
根据AI提示排查vue前端项目
前端·javascript·vue.js
happymaker06266 小时前
web前端学习日记——DAY05(定位、浮动、视频音频播放)
前端·学习·音视频
~无忧花开~7 小时前
React状态管理完全指南
开发语言·前端·javascript·react.js·前端框架
LegendNoTitle7 小时前
计算机三级等级考试 网络技术 选择题考点详细梳理
服务器·前端·经验分享·笔记·php
@大迁世界7 小时前
1.什么是 ReactJS?
前端·javascript·react.js·前端框架·ecmascript
BJ-Giser8 小时前
Cesium 基于EZ-Tree的植被效果
前端·可视化·cesium
王码码20359 小时前
Flutter for OpenHarmony:Flutter 三方库 algoliasearch 毫秒级云端搜索体验(云原生搜索引擎)
android·前端·git·flutter·搜索引擎·云原生·harmonyos
发现一只大呆瓜9 小时前
深入浅出 AST:解密 Vite、Babel编译的底层“黑盒”
前端·面试·vite