摘要:因?yàn)樽柚故录芭莸男袨橹荒苡糜诤铣墒录?,沒法阻止原生事件的冒泡。同時(shí)的創(chuàng)建和冒泡是在原生事件冒泡到最頂層的之后的。淺析之事件系統(tǒng)一
上篇文章中,我們談到了React事件系統(tǒng)的實(shí)現(xiàn)方式,和在React中使用原生事件的方法,那么這篇文章我們來繼續(xù)分析下,看看React中合成事件和原生事件混用的各種情況。
上一個(gè)例子在上篇文章中,我們舉了個(gè)例子。為了防止大家不記得,我們來看看那個(gè)例子的代碼。
class App extends React.Component { constructor(props){ super(props); this.state = { show: false } this.handleClick = this.handleClick.bind(this) this.handleClickImage = this.handleClickImage.bind(this); } handleClick(){ this.setState({ show: true }) } componentDidMount(){ document.body.addEventListener("click", e=> { this.setState({ show: false }) }) } componentWillUnmount(){ document.body.removeEventListener("click"); } handleClickImage(e){ console.log("in this ") e.stopPropagation(); } render(){ return () } } ReactDOM.render(, document.getElementById("root"));
這有什么問題呢? 問題就在于,如果我們點(diǎn)擊image的內(nèi)部依舊可以收起Image,那么這是為什么呢?這是因?yàn)槲覀兗皶r(shí)點(diǎn)擊了Image的內(nèi)部,body上綁定的事件處理器依舊會(huì)執(zhí)行,這樣就讓我們的image收起來了。那我們?nèi)绻幌胱宨mage收起來改怎么做呢?
首先的想法是停止冒泡,如果我們在img-container中就停止冒泡了是不是就可以讓image不消失了呢?比如這樣:
... handleClickImage(e){ e.preventDefault(); e.stopPropagation(); } render(){ return () } ...
Open In CodePen
在這里我們定義一個(gè)handleClickImage的方法,在其中我們執(zhí)行取消默認(rèn)行為和停止冒泡。那是似乎效果并不是我們想要的。因?yàn)樽柚筊eact事件冒泡的行為只能用于React合成事件中,沒法阻止原生事件的冒泡。同樣用React.NativeEvent.stopPropagation()也是無法阻止冒泡的。
如何解決這樣的問題呢?首先,盡量的避免混用合成事件和原生事件。需要注意的點(diǎn)是:
阻止react 合成事件冒泡并不會(huì)阻止原生時(shí)間的冒泡,從上邊的例子我們已經(jīng)看到了,及時(shí)使用stopPropagation也是無法阻止原生時(shí)間的冒泡的。
第二點(diǎn)需要注意的是,取消原生時(shí)間的冒泡會(huì)同時(shí)取消React Event。并且原生事件的冒泡在react event的觸發(fā)和冒泡之前。同時(shí)React Event的創(chuàng)建和冒泡是在原生事件冒泡到最頂層的component之后的。我們來看這個(gè)例子:
class App extends React.Component { render(){ return; } } class GrandPa extends React.Component { constructor(props){ super(props); this.state = {clickTime: 0}; this.handleClick = this.handleClick.bind(this); } handleClick(){ console.log("React Event grandpa is fired"); this.setState({clickTime: new Date().getTime()}) }; componentDidMount(){ document.getElementById("grandpa").addEventListener("click",function(e){ console.log("native Event GrandPa is fired"); }) } render(){ return ( ) } } class Dad extends React.Component { constructor(props){ super(props); this.state = {clickTime:0}; this.handleClick=this.handleClick.bind(this); } componentDidMount(){ document.getElementById("dad").addEventListener("click",function(e){ console.log("native Event Dad is fired"); e.stopPropagation(); }) } handleClick(){ console.log("React Event Dad is fired") this.setState({clickTime: new Date().getTime()}) } render(){ return (GrandPa Clicked at: {this.state.clickTime}
) } } class Son extends React.Component { constructor(props){ super(props); this.state = {clickTime:0}; this.handleClick=this.handleClick.bind(this); } handleClick(){ console.log("React Event Son is fired"); this.setState({clickTime: new Date().getTime()}) } componentDidMount(){ document.getElementById("son").addEventListener("click",function(e){ console.log("native Event son is fired"); }) } render(){ return (Dad Clicked at: {this.state.clickTime}
) } } ReactDOM.render(Son Clicked at: {this.state.clickTime}
, document.getElementById("root"));
Open in CodePen
在這個(gè)例子中我們有三個(gè)component,Son Dad,Grandpa。同時(shí)定義了React Event handler 和 native event handler,并在Dad的native Event handler中stopPropagation,當(dāng)我們點(diǎn)擊Son or Dad component的時(shí)候會(huì)發(fā)現(xiàn),React Event handler并沒有被trigger。
console里的output為:
"native Event son is fired" "native Event Dad is fired"
這就說明native Event的停止冒泡可以阻斷所有的React Event。所以即使我們是在Dad上停止冒泡的,依舊阻斷了Son上的React Event。
同時(shí)如果我們把dad上的stopPropagation remove掉我們會(huì)看到如下結(jié)果:
"native Event son is fired" "native Event Dad is fired" "native Event GrandPa is fired" "React Event Son is fired" "React Event Dad is fired" "React Event grandpa is fired"
這就說明React的合成時(shí)間是在原生事件冒泡到最頂層組件結(jié)束后才創(chuàng)建和冒泡的,也是符合React的原理,因?yàn)樵谑菍?shí)現(xiàn)的時(shí)候React只是將一個(gè)Event listener 掛在了最頂層的組件上,其內(nèi)部一套自己的機(jī)制進(jìn)行事件的管理。
淺析React之事件系統(tǒng)(一)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/81409.html
摘要:合成事件的使用方式在中不會(huì)把所有的事件處理器綁定到相應(yīng)的真實(shí)的節(jié)點(diǎn)上,而是使用一個(gè)統(tǒng)一的事件監(jiān)聽器,把所有的事件綁定在最外層。在之前開發(fā)者需要為了優(yōu)化性能需要自己來優(yōu)化自己的事件處理器的代碼,現(xiàn)在幫助你完成了這些工作。 大家周末好,2016年的最后幾篇文章開始寫到了React的一些東西,那么最近就來一些圖表君對于React的簡單總結(jié)和理解,那么今天就開始第一篇,說一說React的事件系...
摘要:接下來我看看一下函數(shù)我們先按照分支走為讀取是里的對象,饒了這大的一個(gè)圈子,那么接下來一起來看一看對你的輸入配置做了怎么樣的處理吧 打開webpeck-cli下的convert-argv.js文件 // 定義options為空數(shù)組 const options = []; // webpack -d 檢查 -d指令 if (argv.d) { //... } ...
摘要:它由微軟架構(gòu)師和開發(fā),通過利用微軟圖形系統(tǒng)和的互聯(lián)網(wǎng)應(yīng)用派生品的特性來簡化用戶界面的事件驅(qū)動(dòng)程序設(shè)計(jì)。微軟的和架構(gòu)師之一于年在他的博客上發(fā)表了。更改時(shí)會(huì)得到提醒這個(gè)情況是一個(gè)單向流。 前言 記得四個(gè)月前有一次面試,面試官問我 MVVM 是什么,MVVM 的本質(zhì)是什么。我大腦一片混亂,那時(shí)我對 MVVM 的認(rèn)知就只是雙向綁定和Vue,以這個(gè)關(guān)鍵字簡單回答了幾句,我反問 MVVM 的本質(zhì)是...
摘要:通過管理組件通信通過驅(qū)動(dòng)視圖比較差異進(jìn)行更新操作作者第七頁鏈接來源知乎著作權(quán)歸作者所有,轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)。達(dá)到無刷新的效果。對象的狀態(tài)不受外界影響。對象代表一個(gè)異步操作,有三種狀態(tài)進(jìn)行中已完成,又稱和已失敗。 以下問題解釋非本人原創(chuàng),是根據(jù)面試經(jīng)驗(yàn)整理后覺得更容易理解的解釋版本,歡迎補(bǔ)充。 一. 輸入url后的加載過程 從輸入 URL 到頁面加載完成的過程中都發(fā)生了什么 計(jì)算機(jī)...
摘要:通過管理組件通信通過驅(qū)動(dòng)視圖比較差異進(jìn)行更新操作作者第七頁鏈接來源知乎著作權(quán)歸作者所有,轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)。達(dá)到無刷新的效果。對象的狀態(tài)不受外界影響。對象代表一個(gè)異步操作,有三種狀態(tài)進(jìn)行中已完成,又稱和已失敗。 以下問題解釋非本人原創(chuàng),是根據(jù)面試經(jīng)驗(yàn)整理后覺得更容易理解的解釋版本,歡迎補(bǔ)充。 一. 輸入url后的加載過程 從輸入 URL 到頁面加載完成的過程中都發(fā)生了什么 計(jì)算機(jī)...
閱讀 2868·2021-11-19 09:40
閱讀 3726·2021-11-15 18:10
閱讀 3309·2021-11-11 16:55
閱讀 1276·2021-09-28 09:36
閱讀 1682·2021-09-22 15:52
閱讀 3392·2019-08-30 14:06
閱讀 1187·2019-08-29 13:29
閱讀 2333·2019-08-26 17:04