React事件机制
最近在阅读《深入React技术栈》一书中,发现了之前使用React中并没有注意到的React事件与浏览器原生事件之间的区别,鉴于好久已经没有写东西了,就想写一下关于React事件的文章。 //代码来源于《深入React技术栈》2.1.4节 class QrCode extends Component { constructor(props) { super(props); this.handleClick = this.handleClick.bind(this); this.handleClickQr = this.handleClickQr.bind(this); this.state = { active: false,}; } componentDidMount() { document.body.addEventListener('click',e => { this.setState({ active: false,}); }); } componentWillUnmount() { document.body.removeEventListener('click'); } handleClick() { this.setState({ active: !this.state.active,}); } handleClickQr(e) { e.stopPropagation(); } render() { return ( <div className="qr-wrapper"> <button className="qr" onClick={this.handleClick}>二维码</button> <div className="code" style={{ display: this.state.active ? 'block' : 'none' }} onClick={this.handleClickQr} > <img src="qr.jpg" alt="qr" /> </div> </div> ); } } 上面代码从感官上感觉确实可以实现要求的组件,但事实上我们运行上述代码可以发现,点击二维码本身也会导致二维码的隐藏,现在就有意思了,我们来仔细分析一下。 如上图所示,在JavaScript中,事件的触发实质上是要经过三个阶段:事件捕获、目标对象本身的事件处理和事件冒泡,假设在
再回到我们刚开始的问题,现在看起来就很没有很费解了,之所以会出现上面的问题是因为我们混用了React的事件机制和DOM原生的事件机制,认为通过: handleClickQr(e) { e.stopPropagation(); } 就能阻止原生的事件传播,其实在事件委托的情形下是不能实现这一点的。当然解决的办法也不复杂,不要将React事件和DOM原生事件混用。 componentDidMount() { document.body.addEventListener('click',e => { this.setState({ active: false,}); }); document.querySelector('.code').addEventListener('click',e => { e.stopPropagation(); }) } componentWillUnmount() { document.body.removeEventListener('click'); document.querySelector('.qr').removeEventListener('click'); } 或者通过事件原件对象中的 componentDidMount() { document.body.addEventListener('click',e => { if (e.target && e.target.matches('div.code')) { return; } this.setState({ active: false,}); }); } 都可以解决异常关闭的问题。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |