DOM 上的手动 innerHTML 修改会停止 ReactJS 侦听器
Manual innerHTML modification on DOM halts ReactJS listeners
我正在学习 ReactJS 和 Node/Express 生态系统(对我来说还处于早期阶段)。我有一个基本的 ReactJS 文件,包括组件定义和渲染调用。它本身按预期工作。出于 quick/easy 调试目的,昨天我在客户端代码中进行了以下更改:
// 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
对于它的价值,我已经尝试了 document.getEle...
作为第一个 JS 被触发,作为最后一个 JS 被触发,并且正如您现在看到的那样,它是 ReactJS 组件的一部分。无论我把它放在代码的哪个位置,结果都是一样的。
我认为原因在于 innerHTML
的工作方式。它完全重新解析并替换子 DOM 节点(即使您使用 += 只是附加新节点),因此它会破坏以前附加到那些 DOM 节点的所有事件处理程序,在你的例子中,React 的 DOM 子树 "managed"。
对于您的情况,您可能需要考虑改用 insertAdjacentHTML
。
来自 MDN 文档 (https://developer.mozilla.org/en-US/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);
我正在学习 ReactJS 和 Node/Express 生态系统(对我来说还处于早期阶段)。我有一个基本的 ReactJS 文件,包括组件定义和渲染调用。它本身按预期工作。出于 quick/easy 调试目的,昨天我在客户端代码中进行了以下更改:
// 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
对于它的价值,我已经尝试了 document.getEle...
作为第一个 JS 被触发,作为最后一个 JS 被触发,并且正如您现在看到的那样,它是 ReactJS 组件的一部分。无论我把它放在代码的哪个位置,结果都是一样的。
我认为原因在于 innerHTML
的工作方式。它完全重新解析并替换子 DOM 节点(即使您使用 += 只是附加新节点),因此它会破坏以前附加到那些 DOM 节点的所有事件处理程序,在你的例子中,React 的 DOM 子树 "managed"。
对于您的情况,您可能需要考虑改用 insertAdjacentHTML
。
来自 MDN 文档 (https://developer.mozilla.org/en-US/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);