#javascript #dom #reactjs #listener #getelementbyid
#javascript #dom #reactjs #прослушиватель #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 amp;amp; 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. Результат один и тот же, независимо от того, где я размещаю его в коде.
Ответ №1:
Я считаю, что причина в том, как 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);