我有以下html文本:
"<span id='capo' class='capo' data-capo=3>Capo 3</span>"
这是通过dangerouslySetInnerHTML
我有一个这样的听众:
componentDidMount() {
document.getElementById('capo').addEventListener('click', this.changeKey);
}
但是,这仅适用于一次单击,此后侦听器不存在。我猜是因为React已经替换了组件(因为我更改了this.changeKey
中的状态),因此侦听器不再存在。
如何可靠地为React组件设置侦听器?
答案 0 :(得分:2)
在这种情况下,您可以利用事件冒泡!
只需将事件侦听器添加到上部元素(带有dangerouslySetInnerHTML
的元素即可)监听点击并确保e.target.id
等于所需的元素ID。
查看下面的示例(它使用dangerouslySetInnerHTML
来说明事件冒泡如何工作以及如何在React中使用它,在现实生活中您不应编写这样的组件):
class Element extends React.Component {
state = {
loadTime: 0,
lastUpdate: 0
};
lastUpdateTimer = null;
componentDidMount() {
this.resetTimer();
this.lastUpdateTimer = setInterval(this.setLastUpdate, 1000);
this.dynamicContentElement.addEventListener("click", this.handleClick)
}
componentWillUnmount() {
clearInterval(this.lastUpdateTimer);
this.dynamicContentElement.removeEventListener(this.handleClick)
}
resetTimer() {
const now = Date.now();
this.setState({
loadTime: now,
lastUpdate: now
});
}
setLastUpdate = () => {
this.setState({
lastUpdate: Date.now()
});
}
getDynamicContent() {
const time = Math.round((this.state.lastUpdate - this.state.loadTime) / 1000);
return {
__html: `<p>
You are here: <strong>${time}</strong> seconods.
<br>
<button id="btn">Click to reset counter</button>
</p>`
};
}
handleClick = (e) => {
if (e.target.id === "btn") {
this.resetTimer();
}
}
render() {
return (
<div>
Dynamic content below:
<div
ref={el => this.dynamicContentElement = el}
dangerouslySetInnerHTML={this.getDynamicContent()}
/>
</div>
);
}
}
ReactDOM.render(
<Element />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
答案 1 :(得分:1)
每当状态发生变化时,React都会删除html并将其替换。
此代码仅在首次加载组件时执行,而不在状态更改和html元素(及其侦听器)被擦除时执行:
componentDidMount() {
document.getElementById('capo').addEventListener('click', this.changeKey);
}
但是此代码将在每次重新渲染组件时运行(因此,每当创建一个新的html元素时,便会附加一个新的侦听器):
componentDidUpdate() {
document.getElementById('capo').addEventListener('click', this.changeKey);
}