javascript - 手动修改 DOM 的 innerHTML 会停止 ReactJS 监听器

标签 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:
document.getElementById('body').innerHTML += xhr.responseText;

xhr 是经过验证的功能性 xmlHttpRequest()。我发出请求,得到响应,然后它按预期呈现给正文。然而,这阻止所有ReactJS组件监听它们的按钮并按照定义触发它们的处理程序。没有控制台反馈或其他迹象表明有任何问题,ReactJS 只是按预期进行第一次渲染,然后默默地停止响应。

如果我注释掉单行 document.getEle... 那么一切都会重新开始工作,包括 React 和 xhr 本身。

我知道在 ReactJS 中,范例不是以这种方式修改 DOM,但我不明白为什么这一行会破坏所有 ReactJS 功能。对于上下文,这是我的代码的一部分:

无论是否注释掉 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>
    );
  }
});

此组件会损坏除非 document.getEle... 被注释掉,否则它可以正常工作。

// 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>
    );
  }
});

以下是我渲染组件的方式:

ReactDOM.render(
  <StateComponent/>,
  document.getElementById('state-point')
);
// similar calls for other components as needed

就其值(value)而言,我尝试了 document.getEle... 作为第一个 JS 触发、最后一个 JS 触发,以及您现在看到的作为 ReactJS 组件的一部分。无论我将其放在代码中的哪个位置,结果都是相同的。

最佳答案

我相信原因是由于 innerHTML 的工作原理。它完全重新解析并替换子 DOM 节点(即使您使用 += 来附加新节点),因此它会销毁先前附加到这些 DOM 节点的所有事件处理程序,在您的情况下,DOM 子树“托管” “通过 react 。 对于您的情况,您可能需要考虑改用 insertAdjacentHTML

来自 MDN 文档 (https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML):

“它不会重新解析正在使用的元素,因此不会破坏元素内的现有元素。”

尝试以下操作:

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

关于javascript - 手动修改 DOM 的 innerHTML 会停止 ReactJS 监听器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39960933/

相关文章:

javascript - 如何将提供者正确附加到reactDOM.render

javascript - 找不到 Reactjs 模块 | CSS导入

javascript - GWT 检查是否安装了 flash

javascript - 如何使 DOM 元素在 SAPUI5 应用程序上可拖动?

jquery - 无法使用 jQuery 从 DOM 访问 document.ready 元素?

java - 如何合并两个具有相同参数的XML文件?

reactjs - 类型错误 : (0 , import_jsx_dev_runtime.jsxDEV) 不是一个函数

javascript - 在javascript中获取历史日期的时区

Javascript通过char Ref将元素插入到带有子元素的可编辑DIV中

javascript - 在 SPA 站点中保持 2 个导航菜单同步