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

如何等待React组件完全渲染并绘制完成,渲染期间显示加载屏?

解决方案

你的核心需求是等待DOM渲染完成+浏览器绘制完成+所有媒体资源加载完成后再显示页面,避免用户看到绘制或资源加载过程,期间用加载屏占位。以下是具体实现方案:

为什么之前的方案不生效

  • 懒加载:仅负责组件代码的延迟加载,和DOM渲染、浏览器绘制完全无关,无法解决你的问题。
  • 空依赖useEffect:在React的DOM提交阶段(即DOM结构更新完成)执行,但此时浏览器还未完成页面绘制,所以仍然会看到绘制过程。

方案一:仅等待DOM绘制完成(适合资源已预加载场景)

利用requestAnimationFrameAPI,它的回调会在浏览器下一次重绘前执行,确保DOM渲染完成且浏览器即将完成绘制时再隐藏加载屏。

import { useState, useEffect } from 'react';

function FormComponent() {
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const rafId = requestAnimationFrame(() => {
      // 此时DOM已渲染完成,浏览器即将完成绘制
      setLoading(false);
    });

    // 组件卸载时取消回调,避免内存泄漏
    return () => cancelAnimationFrame(rafId);
  }, []);

  if (loading) {
    return <div className="loading-screen">加载中...</div>;
  }

  return (
    <div className="form-component">
      <video src="你的视频地址" controls></video>
      <img src="图片1地址" alt="图片1" />
      <img src="图片2地址" alt="图片2" />
      <img src="图片3地址" alt="图片3" />
      {/* 其他表单内容 */}
    </div>
  );
}

export default FormComponent;

方案二:等待DOM绘制+所有媒体资源加载完成(适配你的场景)

因为组件包含视频和图片这些异步加载的资源,即使DOM结构渲染完成,资源未加载完成时浏览器仍会二次绘制,所以需要同时监听资源加载状态:

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

function FormComponent() {
  const [loading, setLoading] = useState(true);
  const totalResources = useRef(4); // 1个视频 + 3张图片
  const loadedResources = useRef(0);

  // 资源加载/失败时的统一处理函数
  const handleResourceReady = () => {
    loadedResources.current += 1;
    if (loadedResources.current === totalResources.current) {
      // 所有资源就绪后,等待绘制完成再隐藏加载屏
      const rafId = requestAnimationFrame(() => {
        setLoading(false);
      });
      return () => cancelAnimationFrame(rafId);
    }
  };

  useEffect(() => {
    // 给所有媒体元素绑定事件监听
    const mediaElements = document.querySelectorAll('video, img');
    mediaElements.forEach(el => {
      el.addEventListener('load', handleResourceReady);
      el.addEventListener('error', handleResourceReady); // 处理加载失败的情况,避免加载屏一直显示
    });

    // 组件卸载时移除监听
    return () => {
      mediaElements.forEach(el => {
        el.removeEventListener('load', handleResourceReady);
        el.removeEventListener('error', handleResourceReady);
      });
    };
  }, []);

  if (loading) {
    return <div className="loading-screen">加载中...</div>;
  }

  return (
    <div className="form-component">
      <video src="你的视频地址" controls onLoad={handleResourceReady} onError={handleResourceReady}></video>
      <img src="图片1地址" alt="图片1" onLoad={handleResourceReady} onError={handleResourceReady} />
      <img src="图片2地址" alt="图片2" onLoad={handleResourceReady} onError={handleResourceReady} />
      <img src="图片3地址" alt="图片3" onLoad={handleResourceReady} onError={handleResourceReady} />
      {/* 其他表单内容 */}
    </div>
  );
}

export default FormComponent;

配套CSS优化(避免内容闪现)

给加载屏和目标组件添加样式,确保加载过程中组件内容完全不可见:

.loading-screen {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background-color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9999;
}

.form-component {
  visibility: hidden; /* 默认隐藏组件 */
}

.form-component.loaded {
  visibility: visible; /* 加载完成后显示 */
}

然后在组件中动态添加loaded类:

return (
  <div className={`form-component ${!loading ? 'loaded' : ''}`}>
    {/* 组件内容 */}
  </div>
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 19:52:35