Javascript 对DOM的手动innerHTML修改会停止JS侦听器

Javascript 对DOM的手动innerHTML修改会停止JS侦听器,javascript,dom,reactjs,listener,getelementbyid,Javascript,Dom,Reactjs,Listener,Getelementbyid,我正在学习ReactJS和Node/Express生态系统(对我来说是早期)。我有一个基本的ReactJS文件,包括组件定义和呈现调用。它可以按预期自行工作。为了快速/轻松地进行调试,昨天我对客户端代码进行了以下更改: // Added HTML id to body tag, no other changes whatsoever to DOM/HTML <body id='body'>...</body> // In client code, added: docu

我正在学习ReactJS和Node/Express生态系统(对我来说是早期)。我有一个基本的ReactJS文件,包括组件定义和呈现调用。它可以按预期自行工作。为了快速/轻松地进行调试,昨天我对客户端代码进行了以下更改:

// Added HTML id to body tag, no other changes whatsoever to DOM/HTML
<body id='body'>...</body>

// In client code, added:
document.getElementById('body').innerHTML += xhr.responseText;
除非注释掉
document.getEle…
,否则此组件会损坏,否则它工作得很好。

// Hello World component: manage cookies and display a simple prop
var HelloWorldComponent = React.createClass({

  componentWillMount: function() {
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function () {
      if( xhr.readyState == 4 && xhr.status == 200 ) {
        // NOTE: this `console.log` gives expected result regardless
        console.log('Performed initial cookie check.  Got response: ' + xhr.responseText);
        // document.getElementById('body').innerHTML += '<div>'+xhr.responseText+'</div>';
      }
      else {
        console.log('Tried initial cookie check.  Got HTTP response status: ' + xhr.status);
      }
    }
    xhr.open('POST', '/cookieCheck');
    xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
    xhr.send();
  },

  render: function() {
    return (
      <h1 id='italic-id' className='red-class'>Hello, {this.props.name}!</h1>
    );
  }
});
// State component to display simple state
var StateComponent = React.createClass({

  // ReactJS Event: this fails with `document.getEle...` appearing elsewhere in the code
  incrementCount: function() {
    this.setState({
      count: this.state.count + 1
    });
  },

  getInitialState: function() {
    return {
      count: 0
    }
  },

  render: function() {
    return (
      <div className='increment-component'>
        <h3 className='red-class'>Count: {this.state.count}.</h3>
        <button onClick={this.incrementCount}>Boing!</button>
      </div>
    );
  }
});
//要显示简单状态的状态组件
var StateComponent=React.createClass({
//ReactJS事件:此操作失败,代码中的其他地方出现“document.getEle…”
递增计数:函数(){
这是我的国家({
计数:this.state.count+1
});
},
getInitialState:函数(){
返回{
计数:0
}
},
render:function(){
返回(
计数:{this.state.Count}。
博恩!
);
}
});
以下是我渲染组件的方式:

ReactDOM.render(
  <StateComponent/>,
  document.getElementById('state-point')
);
// similar calls for other components as needed
ReactDOM.render(
,
document.getElementById('state-point')
);
//根据需要对其他组件进行类似的调用

值得一提的是,我尝试了
document.getEle…
作为第一个启动的JS,作为最后一个启动的JS,以及作为ReactJS组件的一部分。无论我把它放在代码的什么地方,结果都是一样的。

我相信原因在于
innerHTML
的工作方式。它完全重新解析并替换子DOM节点(即使您使用+=只是附加新的DOM节点),因此它会销毁以前附加到这些DOM节点的所有事件处理程序,在您的情况下,是由React“管理”的DOM子树。 对于您的情况,您可能需要考虑使用<代码> StuttRealEntTrML<代码>。 从MDN文档()中:

“它不会重新分析正在使用它的元素,因此不会损坏元素中的现有元素。”

尝试以下方法:

document.getElementById('body').insertAdjacentHTML('beforeend', xhr.responseText);

我相信原因在于
innerHTML
的工作方式。它完全重新解析并替换子DOM节点(即使您使用+=只是附加新的DOM节点),因此它会销毁以前附加到这些DOM节点的所有事件处理程序,在您的情况下,是由React“管理”的DOM子树。 对于您的情况,您可能需要考虑使用<代码> StuttRealEntTrML<代码>。 从MDN文档()中:

“它不会重新分析正在使用它的元素,因此不会损坏元素中的现有元素。”

尝试以下方法:

document.getElementById('body').insertAdjacentHTML('beforeend', xhr.responseText);