当前位置: 首页 > news >正文

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

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

实现思路

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

其中实现的关键为:

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

具体实现

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 对象不存在。可通过条件判断避免错误
useEffect(() => {if (typeof window === 'undefined') return;// 监听逻辑
}, []);
  1. 组件卸载时清理:必须在 componentWillUnmount 或 useEffect 返回的清理函数中移除事件监听,防止内存泄漏。

封装自定义 hook

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

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>);
}

在这里插入图片描述

http://www.xdnf.cn/news/932491.html

相关文章:

  • 2025HNCTF - Crypto
  • webstorm 配置Eslint
  • Springboot 基于MessageSource配置国际化
  • C#调用Rust动态链接库DLL的案例
  • ​RBAC(基于角色的访问控制)权限管理详解
  • 学习日记-day24-6.8
  • 鸿蒙API自翻译
  • 70常用控件_QVBoxLayout的使用
  • 指针的使用——字符、字符串、字符串数组(char*)
  • C++进阶--C++11--智能指针(重点)
  • 12.7Swing控件6 JList
  • gitcode与github加速计划
  • LabVIEW Modbus 主站冗余控制
  • css | class中 ‘.‘ 和 ‘:‘ 的使用 | 如,何时用 .is-selected{ ... } 何时用 :hover{...}?
  • 3Ds Max 2026安装包+教程网盘下载与安装教程指南
  • [特殊字符] Whisper 模型介绍(OpenAI 语音识别系统)
  • WEB3全栈开发——面试专业技能点P1Node.js / Web3.js / Ethers.js
  • 【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
  • 图神经网络(GNN)模型的基本原理
  • MySQL:CTE 通用表达式
  • 在React 中安装和配置 shadcn/ui
  • 我用Cursor写了一个视频转文字工具,已开源,欢迎体验
  • leetcode 10. 正则表达式匹配
  • 对比传统引擎,Unity3D 在生产配套中的独特优势
  • 【MySQL系列】MySQL 执行 SQL 文件
  • Java后端检查空条件查询
  • 快排图解及JS模板代码
  • 循环变量捕获问题​​
  • redis--黑马点评--分布式锁实现详解
  • 【C/C++】EBO空基类优化介绍