React视频组件加载完成前如何显示骨架屏/占位符并解决尺寸跳变问题?
我来帮你搞定这个问题!要实现视频加载完成前显示骨架屏/占位符,核心是利用HTML5 video元素的加载事件,结合React的状态管理来控制骨架屏的显示与隐藏。下面是具体的实现方案:
改进后的React视频组件
import { useState, useRef, useEffect } from 'react'; const Video = ({ src, type, skeletonStyle }) => { const videoRef = useRef(); // 控制加载状态:初始为true,视频加载完成后切换为false const [isLoading, setIsLoading] = useState(true); // 存储视频实际尺寸,避免骨架屏和最终视频尺寸差异导致的布局跳动 const [videoSize, setVideoSize] = useState({ width: '100%', height: '280px' }); useEffect(() => { const videoElement = videoRef.current; if (!videoElement) return; // 监听视频元数据加载完成事件:此时已获取到视频的宽高、时长等核心信息 const handleMetadataLoaded = () => { setVideoSize({ width: videoElement.videoWidth, height: videoElement.videoHeight }); setIsLoading(false); }; // 监听视频可播放事件:确保视频已加载足够数据可以正常播放 const handleCanPlay = () => { setIsLoading(false); }; // 监听加载错误事件:避免视频加载失败时骨架屏一直显示 const handleLoadError = () => { console.error('视频加载失败,请检查地址或格式'); setIsLoading(false); }; // 绑定事件监听 videoElement.addEventListener('loadedmetadata', handleMetadataLoaded); videoElement.addEventListener('canplay', handleCanPlay); videoElement.addEventListener('error', handleLoadError); // 组件卸载时清理事件监听 return () => { videoElement.removeEventListener('loadedmetadata', handleMetadataLoaded); videoElement.removeEventListener('canplay', handleCanPlay); videoElement.removeEventListener('error', handleLoadError); }; }, [src, type]); return ( <> {/* 加载中显示骨架屏 */} {isLoading ? ( <div style={{ width: videoSize.width, height: videoSize.height, backgroundColor: '#f5f5f5', borderRadius: '8px', display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#999', ...skeletonStyle // 允许外部自定义骨架屏样式 }} > 视频加载中... </div> ) : ( {/* 加载完成显示视频 */} <video ref={videoRef} autoPlay loop controls style={{ width: videoSize.width, height: videoSize.height, borderRadius: '8px' }} > <source src={src} type={type} /> </video> )} </> ); }; export default Video;
关键细节说明
状态与事件联动:
loadedmetadata事件是核心:它会在视频的元数据(宽高、时长等)加载完成后触发,此时我们能拿到视频的真实尺寸,完美解决“默认播放器和实际视频尺寸差异”的问题。canplay作为补充:确保视频已经加载足够数据可以正常播放,避免元数据加载完成但视频仍无法播放的情况。error事件兜底:处理视频加载失败的异常场景,防止骨架屏一直挂着。
布局优化:
通过videoSize状态存储视频真实尺寸,让骨架屏和最终视频的尺寸完全一致,彻底消除布局跳动的问题。如果提前知道视频的固定尺寸,也可以直接传入组件,不用等待元数据加载。自定义扩展:
组件支持传入skeletonStyle属性,你可以根据自己的设计需求自定义骨架屏的样式,比如添加渐变加载动画、调整背景色等。
内容的提问来源于stack exchange,提问作者marija
相关产品推荐
相关产品推荐

