在React组件中重新附加DOM元素

时间:2018-12-03 16:39:56

标签: javascript reactjs

我正面临一种情况,要求我从DOM中完全删除一个元素并重新附加它。更具体地说,在更改视频元素的src时,Airplay功能中的错误会导致缺少曲目信息:

  1. 更改视频元素的src属性,然后开始在Apple TV上播放
  2. 现在将源切换到其他视频
  3. 曲目信息(音频,文本)丢失

我找到了一种解决方法,要求我从DOM中删除视频元素,创建一个新元素,然后将其重新添加到DOM中。做出反应的最佳方法是什么?我尝试设置子组件的key属性,但这似乎没有做到。这是代码的摘录:

class Container extends Component {
   render() {
    <Video key={this.videoElementKey} />
   }
} 

class Video extends Component {
  render() {
   return (
    <video id="vid" className="video-elem" playsInline />
  );

  componentDidMount() {
    console.log("componentDidMount");
   }
}

该组件像我期望的那样被重新安装。这是否意味着视频元素已被删除并再次读取?而且,该组件的ref属性是否刷新了?

2 个答案:

答案 0 :(得分:1)

我不确定您要完成什么,但是,您可能需要检查 unmountComponentAtNode 。它允许您实际卸载自定义组件及其引用,而不仅仅是HTML元素。然后,您可以再次添加组件。

您可以执行以下操作:

ReactDOM.unmountComponentAtNode(document.getElementById(yourNodeID));

抱歉,这不是一个很完整的答案,但是如果不了解您的更多实现,就很难。无论如何,也许它将您指向正确的方向。

答案 1 :(得分:0)

要强制卸载元素,您可以做的是创建两个扩展Video元素的元素,并在更新src时在它们之间切换。使用条件渲染时,每次更改时,其中一个视频组件将被卸载,而另一个视频组件将被安装在其位置。

以下是使用一组视频src的数组的示例:

import React, { Component } from 'react';

const videos = [
  'https://img-9gag-fun.9cache.com/photo/a9KrqE1_460sv.mp4',
  'https://img-9gag-fun.9cache.com/photo/a3Qq4PN_460sv.mp4',
  'https://img-9gag-fun.9cache.com/photo/aE2Yq9O_460sv.mp4'
];

class App extends Component {

  constructor(props) {
    super(props);
    this.onNext = this.onNext.bind(this);
    this.state = {
      current: 0
    }
  }

  onNext = event => {
     this.setState((prevState) => ({
       // using modulo to stay within the length of videos array
       current: (prevState.current + 1) % videos.length 
  }));
};

  render() {
    return (
      <div className="App">
          // switching between two video components if index is odd/even
        { this.state.current % 2 === 1
          ? <One current={this.state.current} />
          : <Two current={this.state.current} /> }
        <hr />
        <button onClick={this.onNext}>Next video</button>
      </div>
    );
  }
}

class Video extends Component {
  render() {
    return (
      <video key={'key-'+this.props.current} id="vid" className="video-elem" playsInline src={videos[this.props.current]}  />
    );
  }

  componentDidMount() {
    console.log("componentDidMount");
  }
  componentWillUnmount() {
    console.log("componentWillUnmount");
  }
}

class One extends Video {}

class Two extends Video {}

export default App;

正在运行example on repl.it