仅渲染 DOM 中的子元素而不是整个 JSX 元素

问题描述

我从一个展示如何使用名为 videoJS 的 npm 库显示视频的用户那里复制了这个文件

import React,{ useEffect,useRef } from 'react'
import VideoJs from 'video.js'


const videoJsOptions = {
  controls: true,autoplay: true,fluid: false,loop: true,width: '100%',aspectRatio: '4:3',children: [
      'MediaLoader'
  ],}

const VideoPlayer = ({ url }) => {
  const videoContainer = useRef()

  //  Setup the player
  useEffect(() => {

    //  Setting content like this because player.dispose() remove also the html content
    videoContainer.current.innerHTML = `
      <div data-vjs-player>
        <video class="video-js" />
      </div>
    `

    //  Setting logger level to all for dev
    if (process.env.NODE_ENV === 'development') {
      VideoJs.log('all')
    }

    const player = VideoJs(videoContainer.current.querySelector('video'),videoJsOptions,async () => {
      player.src({ src: url,type: 'video/mp4' });
    })

    //  When destruct dispose the player
    return () => player.dispose()
  },[url])

  console.log(videoContainer)
  
  return <div ref={videoContainer} />
}

export default VideoPlayer

问题在于渲染的父 div 将实际视频推到了页面下方:

enter image description here

我想删除这个父 div,同时只保留视频元素。我该怎么做?

解决方法

您需要加载 video.js CSS 文件。例如:

import 'video.js/dist/video-js.min.css';

在演示中,我从 CDN 加载 CSS 文件,如您所见,看起来不错。

注意:该演示使用我在 React 中实现的 video.js。内部组件 Player 向父级公开了一个命令式 API,并且由于内部的 JSX 不依赖于更改道具,因此不会重新渲染实际的 DOM。它只会在卸载时处理播放器。

const { useEffect,useRef,forwardRef,useImperativeHandle } = React;

const videoJsOptions = {
  controls: true,autoplay: true,loop: true,width: '100%',aspectRatio: '16:9',children: [
      'MediaLoader'
  ],}

const Player = forwardRef((_,ref) => {
  const video = useRef();
  const player = useRef();
  
  useEffect(() => {
    player.current = videojs(video.current,videoJsOptions);
    
    return () => {
      player.current.dispose();
    };
  },[]);
  
  useImperativeHandle(ref,() => ({
    play: (src,type) => {
      const p = player.current;
      
      p.ready(() => {
        p.src({ src,type });
      });
    }
  }));
  
  return (
    <div data-vjs-player>
      <video className="video-js" ref={video} />
    </div>
  );
});

const VideoPlayer = ({ url,type = 'video/mp4' }) => {
  const player = useRef();
  
  useEffect(() => {
    player.current.play(url,type);
  },[url,type]);
  
  return <Player ref={player} />;
}

ReactDOM.render(
  <VideoPlayer url="https://www.learningcontainer.com/wp-content/uploads/2020/05/sample-mp4-file.mp4" />,root
);
html,body {
  margin: 0;
}
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/video.js/7.0.0/video.min.js" integrity="sha512-LiILFcpZ9QKSH41UkK59Zag/7enHzqjr5lO2M0wGqGn8W19A/x2rV3iufAHkEtrln+Bt+Zv1U6NlLIp+lEqeWQ==" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/video.js/7.0.0/alt/video-js-cdn.min.css" integrity="sha512-zki7IiwYvLzVZouKA+V/vtIuW7cK8M2ug1kaRBItuBWG8TDvA6jrtjhKPOrz3RFGpt9OQC/xE7DUfsrHxoBXxg==" crossorigin="anonymous" />

<div id="root"></div>