如何在React中用变量动态切换Video.js的视频源URL?
动态切换Video.js视频源的解决方案
问题分析
你遇到的核心问题点:
- VideoJS组件未正确接收并处理动态变化的视频源参数,仅依赖
options.sources加载视频,但你传递的source和type属性未被组件处理 - 切换视频时,
options对象未更新sources字段,导致组件无法感知视频源变化 handlePlayerReady中的playerRef是局部变量,无法在组件外部复用
修复步骤
1. 调整VideoJS组件,确保正确响应视频源变化
修改VideoJS.tsx,优化播放器初始化与更新逻辑,确保sources变化时能正确切换视频:
export const VideoJS = (props: any) => { const videoRef = useRef<HTMLDivElement | null>(null); const playerRef = useRef<videojs.Player | null>(null); const { options, onReady } = props; useEffect(() => { if (!playerRef.current) { const videoElement = document.createElement("video-js"); videoElement.classList.add("vjs-big-play-centered"); videoRef.current?.appendChild(videoElement); const player = playerRef.current = videojs(videoElement, options, () => { videojs.log("player is ready"); onReady && onReady(player); }); } else { const player = playerRef.current; // 仅在sources变化时更新视频源 if (options.sources) { player.src(options.sources); } player.autoplay(options.autoplay); } }, [onReady, options]); useEffect(() => { const player = playerRef.current; return () => { if (player && !player.isDisposed()) { player.dispose(); playerRef.current = null; } }; }, []); return ( <div data-vjs-player> <div ref={videoRef} /> </div> ); }; export default VideoJS;
2. 在Form.tsx中维护视频切换状态并传递正确的options
不需要渲染多个VideoJS组件,只需维护一个组件,通过状态切换动态更新视频源:
import { useState, useRef } from 'react'; import VideoJS from './VideoJS'; import videojs from 'video.js'; // 假设已获取选中的项目列表(从JSON文件读取) const selectedItems = [/* 结构示例:{ video_url: "xxx.mp4" } */]; const Form = () => { const [currentVideoIndex, setCurrentVideoIndex] = useState(0); const playerRef = useRef(null); // 全局播放器引用,方便后续控制 const handlePlayerReady = (player: any) => { playerRef.current = player; player.on('waiting', () => { videojs.log('player is waiting'); }); player.on('dispose', () => { videojs.log('player will dispose'); }); }; // Next按钮切换视频逻辑 const handleNext = () => { if (currentVideoIndex < selectedItems.length - 1) { setCurrentVideoIndex(prev => prev + 1); } }; // 动态生成包含当前视频源的配置 const videoJSOptions = { autoplay: true, controls: true, responsive: true, fluid: true, sources: [{ src: selectedItems[currentVideoIndex]?.video_url, type: 'video/mp4' }] }; return ( <div> <VideoJS options={videoJSOptions} onReady={handlePlayerReady} /> <button onClick={handleNext} disabled={currentVideoIndex >= selectedItems.length - 1} > Next </button> </div> ); }; export default Form;
关键说明
- 只保留一个VideoJS组件,通过更新
options.sources实现视频切换,避免重复渲染播放器 - 将
playerRef提升到Form组件全局作用域,方便后续对播放器进行精细化控制(比如切换时暂停上一个视频) - 确保
sources是数组格式,符合Video.js的参数要求 - 移除了VideoJS组件中不必要的依赖项,避免无效重复执行逻辑
内容的提问来源于stack exchange,提问作者Samnita
相关产品推荐
相关产品推荐

