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

Javascript 在React组件中重新附加DOM元素,javascript,reactjs,Javascript,Reactjs,我面临的情况是需要从DOM中完全删除一个元素并重新连接它。更具体地说,当更改视频元素的src时,Airplay功能中的错误会导致缺少曲目信息: 更改videoelement的src属性并开始在Apple TV上播放 现在将源切换到其他视频 曲目信息(音频、文本)丢失 我找到了一个解决方法,需要从DOM中删除视频元素,创建一个新的元素,然后将其重新添加到DOM中。使用react执行此操作的最佳方法是什么?我尝试设置我的子组件的键属性,但这似乎不起作用。以下是代码的摘录: class Contain

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

  • 更改videoelement的src属性并开始在Apple TV上播放
  • 现在将源切换到其他视频
  • 曲目信息(音频、文本)丢失
  • 我找到了一个解决方法,需要从DOM中删除视频元素,创建一个新的元素,然后将其重新添加到DOM中。使用react执行此操作的最佳方法是什么?我尝试设置我的子组件的键属性,但这似乎不起作用。以下是代码的摘录:

    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");
       }
    }
    
    类容器扩展组件{
    render(){
    }
    } 
    类视频扩展组件{
    render(){
    返回(
    );
    componentDidMount(){
    log(“componentDidMount”);
    }
    }
    

    组件会像我预期的那样重新安装。这是否意味着videoelement会被删除并重新读取?此外,组件的ref属性是否已刷新?

    我不确定您试图完成什么,但您可能需要检查。它允许您实际卸载自定义组件和ref然后,你可以再次添加你的组件

    您可以执行以下操作:

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

    很抱歉,这不是一个非常完整的答案,但是如果不了解更多的实现,这很难。无论如何,它可能为您指明了正确的方向。

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

    下面是使用一组视频
    src
    s的示例:

    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;
    
    import React,{Component}来自'React';
    常量视频=[
    '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'
    ];
    类应用程序扩展组件{
    建造师(道具){
    超级(道具);
    this.onNext=this.onNext.bind(this);
    此.state={
    电流:0
    }
    }
    onNext=事件=>{
    this.setState((prevState)=>({
    //使用模保持在视频数组长度内
    当前:(prevState.current+1)%videos.length
    }));
    };
    render(){
    返回(
    //如果索引为奇数/偶数,则在两个视频组件之间切换
    {this.state.current%2==1
    ? 
    :  }
    
    下一个视频 ); } } 类视频扩展组件{ render(){ 返回( ); } componentDidMount(){ log(“componentDidMount”); } 组件将卸载(){ log(“componentWillUnmount”); } } 第一类扩展了视频{} 第二类扩展了视频{} 导出默认应用程序;

    运行。

    是的,
    应该会有帮助。通过您的示例,很难意识到什么是错的,因为
    没有任何共同之处。在您的情况下,因为您需要在
    src
    更改后重新安装
    ,我相信您可以使用
    键={this.props.urltovide}src={this.props.urltovide}
    只需将该
    用作一个组件,并通过更改道具进行渲染。这样会更容易进行跟踪。很抱歉,孩子的命名错误。我修复了这个问题,视频组件现在在容器组件中被引用。但是,重新安装视频组件似乎不会从容器中删除HTML5视频元素由于上述Airplay实现中的错误,这正是我所需要的。在普通JavaScript中,document.body.removeChild(document.getElementById('vid'));Hey@DanielSilhavy查看我下面的答案,它通过react从DOM中删除组件谢谢你的回答,仍然不确定这是否是我需要的。更准确地说,我需要能够真正从DOM中删除元素。我希望react在重新安装组件时会这样做,但显然这不是ca我有点惊讶,这是如此棘手。所以在我的例子中,没有反应,我只是这样做:
    document.body.removeChild(video);
    视频是
    document.getElementById(“video”)
    好的,如果您想从DOM中删除HTML元素(节点),那么您需要执行类似于您在上面的评论中发布的操作。React不会删除元素本身,因为它需要一些节点来(重新)删除挂载组件…所以,是的,我之前的答案只有在移除元素/节点并且由于某种原因连接到它的组件没有被移除时才有用(在这种情况下,即使你看不到它,它也会留在内存中)。