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

React JS中窗口大小改变时增减类名的实现及classList报错解决

报错原因
  • 监听函数执行时目标DOM元素还未渲染完成/已经被卸载,document.getElementById返回null,调用classList方法自然抛出空指针错误
  • 全局绑定的resize事件没有在组件卸载时清除,会造成内存泄漏,也会在组件销毁后触发时访问不存在的DOM
  • React中直接操作原生DOM不符合声明式编程的思路,容易出现状态和视图不同步的问题
正确实现方案

采用状态驱动视图的思路,完全避免直接操作DOM,从根源解决报错,同时满足业务需求:

  1. 用useState维护三个状态:是否为移动端宽度、详情面板显隐状态、会话面板显隐状态
  2. 用useEffect绑定resize监听,实时更新移动端状态,组件卸载时清除监听
  3. 在JSX中直接通过状态动态拼接类名,不需要手动操作DOM的classList

完整代码示例

import { useState, useEffect } from 'react';

function YourComponent() {
  // 定义状态:是否为移动端宽度、详情面板显隐、会话面板显隐
  const [isMobile, setIsMobile] = useState(window.innerWidth <= 768);
  const [showDetails, setShowDetails] = useState(false);
  const [showConvo, setShowConvo] = useState(false);

  useEffect(() => {
    // 防抖函数,减少resize触发频率,优化性能
    const debounce = (func, delay = 200) => {
      let timer;
      return (...args) => {
        clearTimeout(timer);
        timer = setTimeout(() => func.apply(this, args), delay);
      };
    };

    // 窗口大小变化处理逻辑
    const handleResize = debounce(() => {
      const currentIsMobile = window.innerWidth <= 768;
      setIsMobile(currentIsMobile);
      // 切回大屏时自动重置面板显隐状态,保证大屏下所有面板默认展示
      if (!currentIsMobile) {
        setShowDetails(false);
        setShowConvo(false);
      }
    });

    // 绑定resize监听
    window.addEventListener('resize', handleResize);
    // 组件卸载时清除监听,避免内存泄漏
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  return (
    <div className="container">
      {/* 永久展示的聊天列表面板 */}
      <div 
        className={`chats ${isMobile && showConvo ? 'toggle-chats' : ''}`}
      >
        聊天列表内容
      </div>

      {/* 会话面板:大屏默认展示,移动端点击按钮才展示 */}
      <div 
        className={`convo ${isMobile && !showConvo ? 'toggle-convo' : ''}`}
      >
        会话内容
        {isMobile && <button onClick={() => setShowConvo(false)}>返回列表</button>}
      </div>

      {/* 详情面板:大屏默认展示,移动端点击按钮才展示 */}
      <div 
        className={`details ${isMobile && !showDetails ? 'toggle-details' : ''}`}
      >
        详情内容
      </div>

      {/* 移动端控制按钮组 */}
      {isMobile && (
        <div className="btn-group">
          <button onClick={() => setShowConvo(!showConvo)}>切换会话</button>
          <button onClick={() => setShowDetails(!showDetails)}>切换详情</button>
        </div>
      )}
    </div>
  );
}

export default YourComponent;

对应CSS样式示例

/* 大屏默认三个面板全部展示 */
.chats, .convo, .details {
  display: block;
}
/* 移动端隐藏类 */
.toggle-convo, .toggle-details, .toggle-chats {
  display: none;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 03:24:03