Dan*_*ana 10 javascript html5-video reactjs
我是ReactJS(0.13.1)的新手,我在我的应用程序中创建了一个组件来显示HTML5视频.
它似乎工作得很完美,但仅限于第一次选择.当您从一个视频切换到另一个视频时(this.props.video更改时),实际显示并在页面中播放的视频不会更改.
我可以<source src='blah.mp4' />在Chrome检查器中看到元素更新,但页面中实际呈现的视频不会更改,并且如果已经存在则继续播放.在Safari和Firefox中也会发生同样的事情.所有其他元素也都适当更新.
有任何想法吗?
无论如何我的组件如下:
(function(){
var React = require('react');
var VideoView = React.createClass({
render: function(){
var video = this.props.video;
var title = video.title === ''? video.id : video.title;
var sourceNodes = video.media.map(function(media){
media = 'content/'+media;
return ( <source src={media} /> )
});
var downloadNodes = video.media.map(function(media){
var ext = media.split('.').slice(-1)[0].toUpperCase();
media = 'content/'+media;
return (<li><a className="greybutton" href={media}>{ext}</a></li>)
});
return (
<div className="video-container">
<video title={title} controls width="100%">
{sourceNodes}
</video>
<h3 className="video-title">{title}</h3>
<p>{video.description}</p>
<div className="linkbox">
<span>Downloads:</span>
<ul className="downloadlinks">
{downloadNodes}
</ul>
</div>
</div>
)
}
});
module.exports = VideoView;
})();
Run Code Online (Sandbox Code Playgroud)
更新:
用另一种方式描述它:
我有一个链接列表与onClick处理程序,设置组件的道具.
当我第一次点击视频链接("Video Foo")时,我得到了
<video title="Video Foo" controls>
<source src="video-foo.mp4"/>
<source src="video-foo.ogv"/>
</video>
Run Code Online (Sandbox Code Playgroud)
并出现"Video Foo"并可以播放.
然后,当我点击下一个("视频栏")时,DOM会更新,我会得到
<video title="Video Bar" controls>
<source src="video-bar.mp4"/>
<source src="video-bar.ogv"/>
</video>
Run Code Online (Sandbox Code Playgroud)
然而它仍然是"视频Foo",可见并且可以播放.
就像浏览器加载媒体一样,<video>它忽略了对<source>元素的任何更改.
小智 10
我在这里描述了一些纯JavaScript的方法.基于此,我找到了适合我的React解决方案:
使用src视频本身的属性:
var Video = React.createComponent({
render() {
return <video src={this.props.videoUrl} />;
}
});
Run Code Online (Sandbox Code Playgroud)
Dana的答案是扩展此解决方案的绝佳选择.
使用.load()视频元素调用:
var Video = React.createComponent({
componentDidUpdate(_prevProps, _prevState) {
React.findDOMNode(this.refs.video).load(); // you can add logic to check if sources have been changed
},
render() {
return (
<video ref="video">
{this.props.sources.map(function (srcUrl, index) {
return <source key={index} src={srcUrl} />;
})}
</video>
);
}
});
Run Code Online (Sandbox Code Playgroud)UPD:
当然可以key为<video>标签添加唯一属性(例如根据您的来源),因此当源更改时,它也会被更改.但它会导致<video>完全重新渲染,并可能导致一些UI闪烁.
var Video = React.createComponent({
render() {
return (
<video key={this.props.videoId}>
{this.props.sources.map(function (srcUrl, index) {
return <source key={index} src={srcUrl} />;
})}
</video>
);
}
});
Run Code Online (Sandbox Code Playgroud)Hos*_*rad 10
我遇到了同样的问题,并且无法访问<video>HTML 标签,因为我使用库来渲染视频(而不是本机<video>HTML 标签),该库在内部负责渲染<video>标签。
在这种情况下,我找到了另一种解决方案,我认为它可以更好地解决同一问题。
前:
<VideoLibrary src={this.props.src} />
Run Code Online (Sandbox Code Playgroud)
后:
<React.Fragment key={this.props.src}>
<VideoLibrary src={this.props.src} />
</React.Fragment>
Run Code Online (Sandbox Code Playgroud)
或者,如果您使用本机<video>HTML 标记,则为:
<React.Fragment key={this.props.src}>
<video src={this.props.src} />
</React.Fragment>
Run Code Online (Sandbox Code Playgroud)
这样 React 将渲染不同的视频标签,因为srcprop 会不同,因此每次渲染不同的 HTML 标签以避免此问题。
我发现这种方式更干净、更简单,并且无论您是否有权访问<video>HTML 标记,都可以在这两种情况下使用。
找到答案
当元素已经插入到视频或音频元素中时,动态修改源元素及其属性将不起作用。要更改正在播放的内容,只需直接使用媒体元素上的 src 属性,可能会使用 canPlayType() 方法从可用资源中进行选择。通常,在解析文档后手动操作源元素是一种不必要的复杂方法
https://html.spec.whatwg.org/multipage/embedded-content.html#the-source-element
它非常笨拙且脆弱,但它为我的案例完成了工作。
(function(){
var React = require('react');
var VideoView = React.createClass({
pickSource: function(media){
var vid = document.createElement('video');
var maybes = media.filter(function(media){
var ext = media.split('.').slice(-1)[0].toUpperCase();
return (vid.canPlayType('video/'+ext) === 'maybe');
});
var probablies = media.filter(function(media){
var ext = media.split('.').slice(-1)[0].toUpperCase();
return (vid.canPlayType('video/'+ext) === 'probably');
});
var source = '';
if (maybes.length > 0) { source = maybes[0]; }
if (probablies.length > 0) { source = probablies[0]; }
source = (source === '')? '' : 'content/'+source;
return source;
},
render: function(){
var video = this.props.video;
var title = video.title === ''? video.id : video.title;
var src = this.pickSource(video.media);
var downloadNodes = video.media.map(function(media){
var ext = media.split('.').slice(-1)[0].toUpperCase();
media = 'content/'+media;
return (
<li><a className="greybutton" href={media}>{ext}</a></li>
)
});
return (
<div className="video-container">
<video title={title} src={src} controls width="100%"></video>
<h3 className="video-title">{title}</h3>
<p>{video.description}</p>
<div className="linkbox">
<span>Downloads:</span>
<ul className="downloadlinks">
{downloadNodes}
</ul>
</div>
</div>
)
}
});
module.exports = VideoView;
})();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11342 次 |
| 最近记录: |