React中iframe加载时显示加载器(onLoad事件未生效)
解决React+Tailwind中Iframe onLoad事件不触发导致加载界面无法关闭的问题
问题分析
你当前的实现用条件渲染切换加载状态和iframe,但可能遇到以下几个问题:
- 缓存导致onLoad不触发:浏览器缓存iframe内容时,再次加载不会触发onLoad事件,加载状态一直保持
true。 - Calendly嵌入的特殊性:Calendly的嵌入内容是动态加载的,原生iframe的onLoad事件可能在Calendly实际内容渲染完成前就触发,或者它的加载逻辑不依赖原生iframe的onLoad。
- 条件渲染的局限性:只有当
isIframeLoading为false时才渲染iframe,若第一次加载时onLoad未触发,iframe不会被渲染,自然无法后续触发事件。
解决方案
方案1:始终渲染iframe,用加载层覆盖(最直接修复)
修改渲染逻辑,不管加载状态都渲染iframe,加载界面作为绝对定位的overlay覆盖在iframe上方,确保iframe始终存在以触发onLoad:
const [isIframeLoading, setIsIframeLoading] = useState(true); return ( <div className="flex justify-center items-center w-full xm:w-3/4 h-full relative"> {/* 始终渲染iframe */} <iframe className="w-full h-full min-h-[1250px] calendly:min-h-[750px] border-0 box-border" src={calendlyEmbed} onLoad={() => setIsIframeLoading(false)} title='Select a Date & Time - Calendly' ></iframe> {/* 加载状态时显示覆盖层 */} {isIframeLoading && ( <div className="absolute inset-0 h-full w-full bg-ac-gray2 brightness-75 rounded-lg animate-pulse"></div> )} </div> );
方案2:监听Calendly官方加载事件(适配Calendly场景)
Calendly提供官方API监听嵌入内容的加载完成事件,比原生iframe onLoad更可靠:
- 在项目中引入Calendly脚本(可放在
public/index.html或组件内动态引入):
<script type="text/javascript" src="https://assets.calendly.com/assets/external/widget.js"></script>
- 在组件中监听
calendly.loaded事件:
import { useEffect, useState } from 'react'; const CalendlyEmbed = () => { const [isIframeLoading, setIsIframeLoading] = useState(true); useEffect(() => { const handleLoaded = () => setIsIframeLoading(false); window.addEventListener('calendly.loaded', handleLoaded); return () => window.removeEventListener('calendly.loaded', handleLoaded); }, []); return ( <div className="flex justify-center items-center w-full xm:w-3/4 h-full relative"> <iframe className="w-full h-full min-h-[1250px] calendly:min-h-[750px] border-0 box-border" src={calendlyEmbed} title='Select a Date & Time - Calendly' ></iframe> {isIframeLoading && ( <div className="absolute inset-0 bg-ac-gray2 brightness-75 rounded-lg animate-pulse"></div> )} </div> ); }; export default CalendlyEmbed;
方案3:避免缓存触发onLoad
如果是浏览器缓存导致onLoad不触发,可给iframe的src添加随机参数强制加载新内容:
const cacheBustedSrc = `${calendlyEmbed}?t=${Date.now()}`; // 将cacheBustedSrc作为iframe的src属性使用
关键说明
- 方案1解决了条件渲染导致iframe未初始化的问题,确保onLoad能被触发;
- 方案2针对Calendly场景,利用官方事件准确捕获内容加载完成时机;
- 方案3适配缓存导致的重复加载不触发onLoad的情况,但会增加加载时间,按需选择。
内容的提问来源于stack exchange,提问作者oussamaZAAM
相关产品推荐
相关产品推荐

