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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 00:45:31