我有这个 html 文本:
"<span id='capo' class='capo' data-capo=3>Capo 3</span>"
Run Code Online (Sandbox Code Playgroud)
这是通过插入的较大 html 的一部分 dangerouslySetInnerHTML
我有一个这样的听众:
componentDidMount() {
document.getElementById('capo').addEventListener('click', this.changeKey);
}
Run Code Online (Sandbox Code Playgroud)
然而,这只适用于一键点击——之后侦听器不存在。我猜是因为 React 已经替换了组件(因为我更改了 中的状态this.changeKey),因此侦听器不再存在。
如何可靠地为 React 组件设置侦听器?
在这种情况下,您可以使用事件冒泡!
只需将您的事件侦听器添加到上层元素(有的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')
);Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)