【问题标题】:ReactJS can't change video and poster videojsReactJS 无法更改视频和海报 videojs
【发布时间】:2014-12-03 00:31:02
【问题描述】:

我想在 selectedVideo 更改时更改视频海报和源 VideoJS

var VideoPlayer = React.createClass({
  render: function() {
    var selectedVideo = this.props.selectedVideo;
    function filterVideo(video) {
      return video.id == selectedVideo;
    }

    var data = this.props.videos.filter(filterVideo);
    return (
      <div className="col-md-6 videoplayer">
        <h2>{data[0].title}</h2>
        <video id="videoplayer" className="video-js vjs-default-skin vjs-big-play-centered" controls preload="none"
          width="100%"
          height="300"
          poster={data[0].poster}
          data-setup="{}">
          <source src={data[0].video} type='video/mp4' />
        </video>
        <div className="video-description">
          {data[0].description}
        </div>
      </div>
    );
  }
});

但我得到了错误:

Uncaught Error: Invariant Violation: ReactMount: Two valid but unequal nodes with the same `data-reactid`: .0.0.1.1 

标题和说明已更改,但视频海报未更改

【问题讨论】:

    标签: reactjs video.js


    【解决方案1】:

    有一个question 可以回答这个问题(我认为它应该适用于您的情况,否则请告诉我)。您可以通过检查播放器是否已更改然后像这样更改 src 来将其更改为 jQuery 中的示例中的 React 代码:

    componentDidUpdate(prevProps) {
        if (prevProps.src !== this.props.src) { //see if the src changes
            if (this.initialized) { //check if the player has been previously initialized
                this.player.src({ //set the players new source
                    src: this.props.src,
                    type: 'video/mp4'
                })
            } else { 
                this.attemptInitialization() //only initialize player if it hasn't been
            }
        }
    }
    

    【讨论】:

    • 修改this.player.src()后,调用this.player.load()
    【解决方案2】:

    1.导入

    import ReactDOM from 'react-dom'
    

    2.内部函数

    this.setstate({vidio:"{new url as a source}") var name = ReactDOM.findDOMNode(this.video) name.src=this.state.video.url 
    

    3.模板

    <VideoPlayer ref={video => this.video = video}src={this.state.video.url}
                           />
    

    【讨论】:

    • 尝试在您的答案中添加额外信息。解释为什么这是最好的方法。
    【解决方案3】:

    不是 100% 相关,但如果您正在寻找一个更“纯粹”的反应解决方案来实现 videoJS 作为一个组件,这就是我所做的......

    上一篇文章是不久前的,我不知道是否有人提出了更好的实现,但是,我所做的如下:

    1. 将 videojs 函数添加为 getInitialState 属性,并将“videoHTML”属性添加到 getInitialState 中。
    2. 在 componentDidMount 方法中生成了我的视频标签和源,并将该变量字符串分配给 videoHTML 状态属性。
    3. 在 componentWillUnmount() 方法中添加了实例化的 vjs 播放器的 dispose() 和初始状态的 replaceState。
    4. 添加了一个组件函数 __initVideo(elem),用于检查传入的元素是否有子元素,如果有则“this.vjsPlayer = this.state.initVideoJS(elem.children[0], {})”。然后我返回 this.vjsPlayer。
    5. 在 render() 方法的附件 div 中,我将 dangerouslySetInnerHTML 属性设置为 this.state.videoHTML 属性,并设置一个调用 __initVideo 函数的 ref,传入 div。

    无法发布任何代码,但这与我能够弄清楚的 videoJS 的纯 React 实现非常接近。

    【讨论】:

      【解决方案4】:

      如果有人需要 FakeRainBrigand 的答案示例,这就是我的视频课程最后的样子。

      Video = React.createClass({
        componentDidMount: function() {
          var video, wrapper;
          wrapper = document.createElement('div');
          wrapper.innerHTML = "<video id='attachmentVideo' class='video-js vjs-default-skin' controls preload='auto' width='640' height='264' poster='" + this.props.thumbnail + "'><source src='" + this.props.url + "' type='video/mp4' /><p className='vjs-no-js'>To view this video please enable JavaScript, and consider upgrading to a web browser that <a href='http://videojs.com/html5-video-support/' target='_blank'>supports HTML5 video</a></p></video>";
          video = wrapper.firstChild;
          this.refs.target.getDOMNode().appendChild(video);
          return videojs(video, {});
        },
        render: function() {
          return (
            <div id="attachmentViewer">
              <h2>{this.props.title}</h2>
              <div id="attachmentVideoContainer" ref="target" />
            </div>
          );
        }
      });
      

      【讨论】:

        【解决方案5】:

        这是破坏性库的问题。基本上发生的事情是你渲染 &lt;video&gt; 元素,然后 VideoJS 在你的 &lt;video&gt; 旁边注入一堆 sibling 元素(子元素很好)。

        React 尝试更新元素,但它无法弄清楚发生了什么,所以它会恐慌并给出错误。

        所以你有两个选择:

        方案一:渲染一个&lt;div ref="target" /&gt;,在componentDidMount和this.refs.target.appendChild(that)中构造video节点,然后手动调用VideoJS。在componentWillRecieveProps中需要直接更新poster img的src。

        选项 2:fork video.js 并使其只发出事件而不是直接修改 DOM。您的组件将对这些事件做出反应、修改状态并渲染海报、按钮等。

        选项 1 更简单,选项 2 可能更高效、更清洁。我会选择选项 1。


        这些都不是很好的解决方案,但是逃离其容器的库不能很好地与 react 配合使用。

        【讨论】:

        • @fakerainbrigand 你能举个例子吗?特别是关于 componentWillReceiveProps 和清理? github.com/videojs/video.js/issues/2006
        • 对我来说,这是 VideoJS 添加的 &lt;video&gt; 的父 div。该 div 和 video 元素具有相同的data-reactid(键)。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-01
        • 1970-01-01
        • 2017-07-25
        • 2012-12-06
        相关资源
        最近更新 更多