先來看這
故事的開頭是這樣的:寫代碼的過程當中,發如今內層用stopPropagation
阻止綁定在document
上的事件的時候,是沒辦法作到的,只能夠阻止outClick事件的觸發。react
class ExampleApplication extends React.Component { componentDidMount() { document.addEventListener('click', () => { alert('document click'); }) } outClick(e) { console.log(e.currentTarget); alert('outClick'); } onClick(e) { console.log(e.currentTarget); alert('onClick'); e.stopPropagation(); } render() { return <div onClick={this.outClick}> <button onClick={this.onClick}> 測試click事件 </button> </div> } }
關於這個問題的解釋,網上五花八門,有些將其歸結爲是因爲事件委託的緣由,例如這篇文章裏說segmentfault
咱們直接在jsx模板上綁定的事件,都是委託在了document上,那天然要比直接在dom上綁定的事件慢了,等document收到事件後纔去e.stopPropagation(),太晚了
其實從上面例子的輸出: 由'onClick',再到'document click'
可知,其實原生document上綁定的事件時最後執行的,因此並非由於document收到事件快慢的緣由而致使這個問題。瀏覽器
真相只有一個,那就是:
出現上述bug的主要緣由是混用瀏覽器原生事件跟React合成事件dom
詳細解釋:React有本身的一套事件處理機制,它會將全部的事件都綁定在document
上,而後再用dispatchEvent統一分發,這時候分發的是合成事件。
而onClick(e)
這時候拿到的e實際上是合成事件,只能阻止合成事件的冒泡。函數
class ExampleApplication extends React.Component { componentDidMount() { document.addEventListener('click', () => { alert('document click'); }) document.getElementById('div1').addEventListener('click', () => { alert('原生outClick'); }) } outClick(e) { console.log(e.currentTarget); alert('合成outClick'); } onClick(e) { console.log(e.currentTarget); alert('onClick'); e.stopPropagation(); } render() { return <div id="div1" onClick={this.outClick}> <button onClick={this.onClick}> 測試click事件 </button> </div> } }
作了點小改動,就是外層的div綁定的函數用原生的方式跟jsx的方式都綁定一次,因此最終的輸出爲測試
'原生outClick', 'onClick','document click'
因此button回調函數裏的stopPropagation
只能阻止合成事件的冒泡,而對於原生綁定的,則不行。this
解決方法有幾種,我我的認爲最簡單的就是直接在onClick
裏利用[event.stopImmediatePropagation()][2]
。原理是這樣的:spa
對於例子一里,document其實綁定了兩個事件:code
// react 合成事件, dispatchEvent裏面執行回調函數 document.addEventListener('click', dispatchEvent); // 瀏覽器原生 document.addEventListener('click', () => { alert('document click'); })
而dispatchEvent
裏的stopImmediatePropagation
可使得綁定在document
上的其餘事件就不會被觸發component
onClick(e) { console.log(e.currentTarget); alert('onClick'); e.nativeEvent.stopImmediatePropagation(); }
固然本篇文章只是爲了拋磚引玉,重點是下一篇的react事件機制,歡迎繼續收看。