只渲染 DOM 中的子元素而不是整个 JSX 元素
Render only child element in DOM instead of the whole JSX element
我从一个显示如何使用名为 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 渲染将实际视频推到页面下方:
我想删除这个父元素 div,同时只保留视频元素。我该怎么做?
您需要加载 video.js CSS 文件。例如:
import 'video.js/dist/video-js.min.css';
在演示中,我从 CDN 加载了 CSS 文件,如您所见,它看起来不错。
注意:该演示使用我在 React 中实现的 video.js。内部组件 Player
向父级公开命令 API,并且由于内部的 JSX 不依赖于更改 props,因此它不会重新渲染实际的 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>
我从一个显示如何使用名为 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 渲染将实际视频推到页面下方:
我想删除这个父元素 div,同时只保留视频元素。我该怎么做?
您需要加载 video.js CSS 文件。例如:
import 'video.js/dist/video-js.min.css';
在演示中,我从 CDN 加载了 CSS 文件,如您所见,它看起来不错。
注意:该演示使用我在 React 中实现的 video.js。内部组件 Player
向父级公开命令 API,并且由于内部的 JSX 不依赖于更改 props,因此它不会重新渲染实际的 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>