在DOM上手动对innerHTML进行修改会暂停ReactJS侦听器 [英] Manual innerHTML modification on DOM halts ReactJS listeners

查看:97
本文介绍了在DOM上手动对innerHTML进行修改会暂停ReactJS侦听器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm learning ReactJS and the Node/Express ecosystem (early days for me). I have a rudimentary ReactJS file including component definitions and rendering calls. It works as expected on its own. For quick/easy debugging purposes, yesterday I made the following changes in the client code:

// 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只是按预期进行第一个渲染,然后静默停止响应.

xhr is a validated, functional xmlHttpRequest(). I make the request, get a response, and it renders to the body as expected. However, this stops all ReactJS components from listening to their buttons and firing their handlers as defined. There is no console feedback or other sign that anything is wrong, ReactJS just does a first render as expected, then silently stops responding.

如果我将单行document.getEle...注释掉,那么一切将再次开始工作,包括React和xhr本身.

If I comment out the single line document.getEle... then everything starts working again, including React and the xhr itself.

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

I know in ReactJS the paradigm is not to modify the DOM in this way, but I fail to see why this one line would break all ReactJS functionality. For context, here is a portion of my code:

无论有没有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...被注释掉,否则它会完美运行.

This component breaks unless document.getEle... is commented out, other wise it works perfectly.

// 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

对于它的价值,我尝试了document.getEle...作为第一个JS触发,作为最后一个JS触发,并且正如您现在所看到的,它已作为ReactJS组件的一部分.无论我将其放置在代码中的何处,结果都是相同的.

For what it's worth, I've tried the document.getEle... as the first JS fired, as the last JS fired, and as you see it now as part of a ReactJS component. The result is the same no matter where I place it in the code.

推荐答案

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

I believe the reason is due to how innerHTML works. It completely re-parse and replace the children DOM nodes (even if you're using += to just append the new ones), so it destroys all the event handlers previously attached to those DOM nodes, in your case the DOM subtree "managed" by React. For your case, you may need to consider using insertAdjacentHTML instead.

从MDN文档( https://developer.mozilla .org/zh-CN/docs/Web/API/Element/insertAdjacentHTML ):

它不会重新解析正在使用它的元素,因此不会破坏该元素内部的现有元素."

"It does not reparse the element it is being used on and thus it does not corrupt the existing elements inside the element. "

尝试以下操作:

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

这篇关于在DOM上手动对innerHTML进行修改会暂停ReactJS侦听器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆