You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中如何随文档宽度变化修改组件状态?

如何在文档宽度变化时更新React组件状态?

嘿,这个需求在React开发里挺常见的,我来给你拆解清楚怎么实现~首先得纠正一个小误区:body元素并没有onChange事件(这个事件主要是给表单元素用的),如果要监听文档/视口的宽度变化,或者body自身的尺寸变化,我们需要用不同的方法,下面分两种场景给你具体方案:

场景1:监听浏览器视口宽度变化(最常见需求)

这是大部分“文档宽度变化”场景的核心需求,比如窗口缩放、设备横竖屏切换时的视口宽度变化。在React里,我们可以通过生命周期钩子(类组件)或者useEffect(函数组件)来绑定window的resize事件:

函数组件实现(React Hooks)

import { useState, useEffect } from 'react';

function WidthAwareComponent() {
  // 初始化状态为当前视口宽度
  const [documentWidth, setDocumentWidth] = useState(window.innerWidth);

  // 定义尺寸变化的处理函数
  const handleResize = () => {
    // 更新视口宽度
    setDocumentWidth(window.innerWidth);
    // 如果需要获取body的实际宽度,可替换为:
    // setDocumentWidth(document.body.offsetWidth);
  };

  useEffect(() => {
    // 组件挂载时绑定resize事件
    window.addEventListener('resize', handleResize);
    
    // 组件卸载时移除事件监听,避免内存泄漏
    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, []); // 空依赖数组确保只在组件挂载时执行一次

  return (
    <div>
      当前文档宽度:{documentWidth}px
    </div>
  );
}

export default WidthAwareComponent;

类组件实现

import React from 'react';

class WidthAwareComponent extends React.Component {
  state = {
    documentWidth: window.innerWidth,
  };

  handleResize = () => {
    this.setState({
      documentWidth: window.innerWidth,
      // 如需body宽度可替换为:document.body.offsetWidth
    });
  };

  componentDidMount() {
    window.addEventListener('resize', this.handleResize);
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.handleResize);
  }

  render() {
    return (
      <div>
        当前文档宽度:{this.state.documentWidth}px
      </div>
    );
  }
}

export default WidthAwareComponent;

场景2:监听body元素自身的尺寸变化(比如内容撑开body宽度)

如果你的需求是body元素自身的宽度变化(而非浏览器视口)——比如动态加载内容导致body宽度被撑开,这时候window.resize事件不会触发,我们需要用ResizeObserver API来监听body的尺寸变化:

函数组件示例

import { useState, useEffect, useRef } from 'react';

function BodyWidthAwareComponent() {
  const [bodyWidth, setBodyWidth] = useState(document.body.offsetWidth);
  // 用ref保存ResizeObserver实例,避免重复创建
  const resizeObserverRef = useRef(null);

  useEffect(() => {
    // 初始化ResizeObserver
    resizeObserverRef.current = new ResizeObserver((entries) => {
      // 提取body元素的尺寸变化信息
      const bodyEntry = entries[0];
      setBodyWidth(bodyEntry.contentRect.width);
    });

    // 开始监听body元素
    const bodyElement = document.body;
    resizeObserverRef.current.observe(bodyElement);

    // 组件卸载时停止监听
    return () => {
      if (resizeObserverRef.current) {
        resizeObserverRef.current.unobserve(bodyElement);
        resizeObserverRef.current.disconnect();
      }
    };
  }, []);

  return (
    <div>
      当前body宽度:{bodyWidth}px
    </div>
  );
}

export default BodyWidthAwareComponent;

额外优化建议

  • 防抖处理:resize事件触发频率极高,建议给处理函数加防抖,避免频繁更新状态影响性能:
    // 简单的防抖函数
    const debounce = (func, delay) => {
      let timeoutId;
      return (...args) => {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => func.apply(this, args), delay);
      };
    };
    
    // 使用防抖后的处理函数
    const handleResize = debounce(() => {
      setDocumentWidth(window.innerWidth);
    }, 100); // 100ms延迟可根据需求调整
    
  • 结合CSS媒体查询:如果只是做响应式UI展示,优先用CSS媒体查询实现;仅当需要在JS中做业务逻辑判断时,再使用上述监听方法。

内容的提问来源于stack exchange,提问作者Anna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:52:14