最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

React中的stopPropagation和preventDefault實(shí)踐記錄

 更新時(shí)間:2025年11月03日 10:00:48   作者:阿藍(lán)灬  
本文詳細(xì)介紹了事件冒泡、捕獲與React合成事件體系下的表現(xiàn)區(qū)別,包括事件傳播階段、處理方式、事件池機(jī)制等核心概念,對(duì)React?stopPropagation和preventDefault相關(guān)知識(shí)感興趣的朋友跟隨小編一起看看吧

事件冒泡、捕獲是DOM事件傳播的核心機(jī)制,而stopPropagationpreventDefault是控制事件行為的關(guān)鍵方法。React的合成事件體系基于原生事件封裝,但在表現(xiàn)上有顯著差異。下面分三部分詳細(xì)說明:

一、事件冒泡與捕獲的區(qū)別

DOM事件傳播遵循“事件流”模型,分為三個(gè)階段(從外到內(nèi)再到外),其中“捕獲”和“冒泡”是核心階段:

階段傳播方向觸發(fā)順序作用
捕獲階段從頂層元素(window)向目標(biāo)元素傳播先執(zhí)行由外向內(nèi)“捕獲”事件,讓上層元素有機(jī)會(huì)在事件到達(dá)目標(biāo)前處理(如全局?jǐn)r截)。
目標(biāo)階段事件到達(dá)實(shí)際觸發(fā)的元素(目標(biāo)元素)中間執(zhí)行目標(biāo)元素的事件處理函數(shù)觸發(fā)。
冒泡階段從目標(biāo)元素向頂層元素(window)傳播后執(zhí)行由內(nèi)向外“冒泡”事件,讓上層元素有機(jī)會(huì)在事件離開目標(biāo)后處理(如事件委托)。

示例

<div id="grandparent">
  <div id="parent">
    <button id="child">點(diǎn)擊</button>
  </div>
</div>

點(diǎn)擊child按鈕時(shí),事件流順序?yàn)椋?/p>

  1. 捕獲階段window → document → grandparent → parent → child(從外到內(nèi));
  2. 目標(biāo)階段child(事件到達(dá)目標(biāo));
  3. 冒泡階段child → parent → grandparent → document → window(從內(nèi)到外)。

核心區(qū)別

  • 傳播方向相反:捕獲是“自上而下”,冒泡是“自下而上”;
  • 觸發(fā)時(shí)機(jī)不同:捕獲階段的事件處理函數(shù)先于冒泡階段執(zhí)行(若同時(shí)綁定)。

二、stopPropagation與preventDefault的作用

兩者都是事件對(duì)象(event)的方法,但作用完全不同:

1.event.stopPropagation()

  • 作用:阻止事件繼續(xù)在事件流中傳播(包括捕獲和冒泡階段)。
  • 效果:事件到達(dá)當(dāng)前元素后,不會(huì)再向其他元素傳播(無論是上層還是下層)。

示例
parent在冒泡階段綁定事件,且child的事件處理中調(diào)用stopPropagation(),則點(diǎn)擊child時(shí),parentgrandparent的冒泡事件不會(huì)觸發(fā)。

2.event.preventDefault()

  • 作用:阻止事件的“默認(rèn)行為”(瀏覽器為某些事件預(yù)設(shè)的行為)。
  • 不影響:事件的傳播(捕獲和冒泡會(huì)正常進(jìn)行)。

常見默認(rèn)行為

  • <a>標(biāo)簽點(diǎn)擊跳轉(zhuǎn);
  • <form>表單提交后刷新頁面;
  • 右鍵點(diǎn)擊彈出上下文菜單。

示例
<a href="https://example.com" onclick="event.preventDefault()">鏈接</a>
點(diǎn)擊鏈接時(shí),不會(huì)跳轉(zhuǎn)(默認(rèn)行為被阻止),但事件仍會(huì)正常冒泡到父元素。

三、React合成事件體系下的表現(xiàn)

React的“合成事件”(SyntheticEvent)是對(duì)原生DOM事件的封裝,目的是統(tǒng)一跨瀏覽器的事件行為,并通過“事件委托”優(yōu)化性能。其表現(xiàn)與原生事件有以下核心差異:

1. 事件委托機(jī)制

React不會(huì)將事件直接綁定到DOM元素上,而是將所有事件委托到根節(jié)點(diǎn)(React 17前是document,17后是掛載的根節(jié)點(diǎn),如#root)。當(dāng)事件觸發(fā)并冒泡到根節(jié)點(diǎn)時(shí),React再根據(jù)事件源分發(fā)到對(duì)應(yīng)的組件處理函數(shù)。

2. 捕獲階段的處理方式

  • 原生事件:通過addEventListener(event, handler, true)的第三個(gè)參數(shù)true綁定捕獲階段的處理函數(shù)。
  • React合成事件:默認(rèn)在冒泡階段處理事件;若需在捕獲階段處理,需在事件名后加Capture后綴(如onClickCapture而非onClick)。

示例

// 父組件在捕獲階段處理事件
<div onClickCapture={() => console.log('父元素捕獲')}>
  <button onClick={() => console.log('子元素冒泡')}>點(diǎn)擊</button>
</div>
// 點(diǎn)擊按鈕時(shí),輸出順序:父元素捕獲 → 子元素冒泡(符合捕獲先于冒泡的規(guī)則)

3.stopPropagation()的差異

  • 原生事件:調(diào)用后會(huì)阻止事件在整個(gè)DOM樹中的傳播(包括到達(dá)React的委托根節(jié)點(diǎn))。
  • React合成事件:調(diào)用e.stopPropagation()只能阻止合成事件的傳播(即其他React組件的事件處理函數(shù)不會(huì)觸發(fā)),但無法阻止原生事件的傳播(因?yàn)樵录呀?jīng)冒泡到了根節(jié)點(diǎn),React只是在此時(shí)分發(fā)合成事件)。

反例

// 子組件(合成事件)
<button 
  onClick={(e) => {
    e.stopPropagation(); // 阻止合成事件傳播
    console.log('子元素合成事件');
  }}
  // 原生事件
  ref={(el) => {
    el?.addEventListener('click', () => console.log('子元素原生事件'));
  }}
>
  點(diǎn)擊
</button>
// 父組件(合成事件)
<div onClick={() => console.log('父元素合成事件')}>
  {/* 子組件 */}
</div>

點(diǎn)擊按鈕時(shí):

  • 子元素的合成事件和原生事件都會(huì)觸發(fā);
  • 父元素的合成事件不會(huì)觸發(fā)(因?yàn)楹铣墒录膫鞑ケ蛔柚梗?/li>
  • 若父元素同時(shí)綁定了原生事件(如addEventListener),則會(huì)觸發(fā)(因?yàn)樵录膫鞑ノ幢蛔柚梗?/li>

4.preventDefault()的差異

  • 作用與原生一致:阻止事件的默認(rèn)行為(如表單提交、鏈接跳轉(zhuǎn))。
  • 注意點(diǎn):React中不能通過return false同時(shí)實(shí)現(xiàn)阻止默認(rèn)行為和傳播(與原生DOM不同)。原生中return false等價(jià)于同時(shí)調(diào)用preventDefault()stopPropagation(),但React中return false無效,必須顯式調(diào)用對(duì)應(yīng)方法。

5. 事件池機(jī)制(React 17前)

React 17之前,合成事件對(duì)象會(huì)被放入“事件池”復(fù)用(性能優(yōu)化),事件處理函數(shù)執(zhí)行完后,事件對(duì)象的屬性會(huì)被清空。因此,異步訪問事件屬性會(huì)失效(需用e.persist()保留)。
React 17后移除了事件池,事件對(duì)象不再被復(fù)用,無需e.persist()。

總結(jié)

場(chǎng)景原生事件React合成事件
傳播階段處理addEventListener(..., true)綁定捕獲事件名加Capture后綴(如onClickCapture
stopPropagation()阻止所有階段的傳播(包括到React根節(jié)點(diǎn))僅阻止合成事件傳播,不影響原生事件傳播
preventDefault()阻止默認(rèn)行為,不影響傳播同原生,需顯式調(diào)用(return false無效)
事件綁定方式直接綁定到DOM元素委托到根節(jié)點(diǎn),通過組件函數(shù)分發(fā)

理解這些差異的核心是:React合成事件是“模擬”原生事件的抽象層,其傳播機(jī)制依賴原生事件的冒泡,但行為上做了統(tǒng)一和限制,以適配組件化開發(fā)需求。

擴(kuò)展:stopPropagation, preventDefault 和 return false 的區(qū)別

stopPropagation, preventDefault 和 return false 的區(qū)別

因?yàn)橛懈?子節(jié)點(diǎn)同在; 因?yàn)橛斜O(jiān)聽事件和瀏覽器默認(rèn)動(dòng)作之分。使用 JavaScript 時(shí)為了達(dá)到預(yù)期效果經(jīng)常需要阻止事件和動(dòng)作執(zhí)行. 一般我們會(huì)用到三種方法, 分別是 stopPropagation()preventDefault() 和 return false。它們之間有什么區(qū)別, 該何時(shí)使用呢? 將在本文中進(jìn)行講解。

監(jiān)聽事件: 指在節(jié)點(diǎn)上能被監(jiān)聽的頁面操作。如: select 節(jié)點(diǎn)的 change 事件, a 節(jié)點(diǎn)的 click 事件。
瀏覽器默認(rèn)動(dòng)作: 指特定頁面元素上帶有的功能。如: 點(diǎn)擊 a 鏈接節(jié)點(diǎn)的跳轉(zhuǎn)動(dòng)作, 表單提交動(dòng)作。

1.stopPropagation()

因?yàn)槭录梢栽诟鲗蛹?jí)的節(jié)點(diǎn)中傳遞,不管是冒泡還是捕獲,有時(shí)我們希望事件在特定節(jié)點(diǎn)執(zhí)行完之后不再傳遞,可以使用事件對(duì)象的 stopPropagation() 方法。
假設(shè)頁面上存在一個(gè)浮動(dòng)彈出層,顯示在最前面,當(dāng)點(diǎn)擊彈出層以外頁面區(qū)域時(shí),隱藏彈出層。為了做到這樣的效果,我們會(huì)監(jiān)聽 documentElement 的 click 事件,一旦事件被觸發(fā)即隱藏彈出層。但是...
這顯然存在問題。當(dāng)用戶點(diǎn)擊彈出層時(shí),我們不希望它隱藏掉。但因?yàn)槭录拿芭輦鬟f,documentElement 的 click 事件也會(huì)被觸發(fā)。這個(gè)時(shí)候,我們可以監(jiān)聽彈出層的 click 事件,并使用 stopPropagation() 方法阻止冒泡。請(qǐng)參考下面的代碼。

// 在彈出對(duì)話框上點(diǎn)擊時(shí), 不進(jìn)行任何頁面操作, 并阻止冒泡
document.getElementById('dialog').onclick = function(ev) {
    ev.stopPropagation();
};
// 在 documentElement 節(jié)點(diǎn)上監(jiān)聽到點(diǎn)擊事件時(shí), 隱藏對(duì)話框
document.documentElement.onclick = function(ev) {
    document.getElementById('dialog').style.display = 'none';
};

stopPropagation() 相當(dāng)好用,可是 IE8 及以前版本都不支持(用jquery就不用考略這點(diǎn)了)。IE 的事件對(duì)象包含特有的屬性 cancelBubble, 只要將它賦值為 false 即可阻止事件繼續(xù)。如:

// 在彈出對(duì)話框上點(diǎn)擊時(shí), 不進(jìn)行任何頁面操作, 并阻止冒泡
document.getElementById('dialog').onclick = function(ev) {
    ev.cancelBubble = false;
};

preventDefault()
一個(gè)帶事件監(jiān)聽的鏈接代碼如下:

<a  οnclick="alert('my name is chic!');">點(diǎn)擊我哦!</a>

點(diǎn)擊該鏈接, 顯示對(duì)話框后跳轉(zhuǎn)頁面。由此可知,除了執(zhí)行監(jiān)聽事件還會(huì)觸發(fā)瀏覽器默認(rèn)動(dòng)作;執(zhí)行監(jiān)聽事件在前,觸發(fā)瀏覽器默認(rèn)動(dòng)作在后。
這里有個(gè)經(jīng)典示例, 我們希望點(diǎn)擊鏈接在新窗口打開頁面,但不希望當(dāng)前頁面跳轉(zhuǎn)。這個(gè)時(shí)候可以使用 preventDefault() 阻止后面將要執(zhí)行的瀏覽器默認(rèn)動(dòng)作。

<a id="link" >W3C 首頁鏈接</a>
<script>
    //在新窗口, 打開頁面
    document.getElementById('link').onclick = function(ev) {
        // 阻止瀏覽器默認(rèn)動(dòng)作 (頁面跳轉(zhuǎn))
        ev.preventDefault();
        // 在新窗口打開頁面
        window.open(this.href);
    };
</script>

return false

退出執(zhí)行,return false 之后的所有觸發(fā)事件和動(dòng)作都不會(huì)被執(zhí)行。有時(shí)候 return false 可以用來替代 stopPropagation() 和 preventDefault(),比如我們上面新窗口打開鏈接的例子,如:

<a id="link" >W3C 首頁鏈接</a> 
<script>
    //在新窗口, 打開頁面
    document.getElementById('link').onclick = function(ev) {
        // 在新窗口打開頁面
        window.open(this.href);
        // 退出執(zhí)行 (在監(jiān)聽事件之后執(zhí)行的瀏覽器默認(rèn)動(dòng)作將不會(huì)被執(zhí)行)
        return false;
    };
</script>

有人認(rèn)為 return false = stopPropagation() + preventDefault(),其實(shí)是錯(cuò)的。return false 不但阻止事件,還可以返回對(duì)象,跳出循環(huán)等... 方便地一刀切而不夠靈活,濫用易出錯(cuò).

到此這篇關(guān)于React中的stopPropagation和preventDefault實(shí)踐記錄的文章就介紹到這了,更多相關(guān)React stopPropagation和preventDefault內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用 React Router Dom 實(shí)現(xiàn)路由導(dǎo)航的詳細(xì)過程

    使用 React Router Dom 實(shí)現(xiàn)路由導(dǎo)航的詳細(xì)過程

    React Router Dom 是 React 應(yīng)用程序中用于處理路由的常用庫(kù),它提供了一系列組件和 API 來管理應(yīng)用程序的路由,這篇文章主要介紹了使用 React Router Dom 實(shí)現(xiàn)路由導(dǎo)航,需要的朋友可以參考下
    2024-03-03
  • 記一個(gè)React.memo引起的bug

    記一個(gè)React.memo引起的bug

    memo可以自己決定是否更新,但它是一個(gè)函數(shù)組件而非一個(gè)類,本文主要介紹了React.memo引起的bug,具有一定的參考價(jià)值,感興趣的可以了解一下
    2022-03-03
  • 在create-react-app中使用sass的方法示例

    在create-react-app中使用sass的方法示例

    這篇文章主要介紹了在create-react-app中使用sass的方法示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-10-10
  • 淺談react?16.8版本新特性以及對(duì)react開發(fā)的影響

    淺談react?16.8版本新特性以及對(duì)react開發(fā)的影響

    本文主要介紹了react?16.8版本新特性以及對(duì)react開發(fā)的影響,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 每天一個(gè)hooks學(xué)習(xí)之useUnmount

    每天一個(gè)hooks學(xué)習(xí)之useUnmount

    這篇文章主要為大家介紹了每天一個(gè)hooks學(xué)習(xí)之useUnmount,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • IntersectionObserver實(shí)現(xiàn)加載更多組件demo

    IntersectionObserver實(shí)現(xiàn)加載更多組件demo

    這篇文章主要為大家介紹了IntersectionObserver實(shí)現(xiàn)加載更多組件demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • React中Ref的作用小結(jié)

    React中Ref的作用小結(jié)

    本文文章介紹了React中的Ref概念,包括其基礎(chǔ)概念、使用方式,并討論了在React中通過Ref操作DOM值時(shí)避免組件不更新的問題,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-11-11
  • React中useState和useEffect的用法詳解

    React中useState和useEffect的用法詳解

    Hooks?發(fā)布之后,函數(shù)組件能擁有自己的?state,React提供了很多內(nèi)置的Hooks,這篇文章就來和大家介紹一下useState?和?useEffect的使用,需要的可以參考一下
    2023-06-06
  • React UI組件庫(kù)ant-design的介紹與使用

    React UI組件庫(kù)ant-design的介紹與使用

    Ant Design是阿里螞蟻金服團(tuán)隊(duì)基于React開發(fā)的ui組件,主要用于中后臺(tái)系統(tǒng)的使用,這篇文章主要介紹了React UI組件庫(kù)ant-design的介紹與使用,需要的朋友可以參考下
    2023-12-12
  • 在React中如何優(yōu)雅的處理事件響應(yīng)詳解

    在React中如何優(yōu)雅的處理事件響應(yīng)詳解

    這篇文章主要給大家介紹了關(guān)于在React中如何優(yōu)雅處理事件響應(yīng)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面跟著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-07-07

最新評(píng)論

东城区| 色达县| 安康市| 贵港市| 太原市| 鲁山县| 井冈山市| 民乐县| 玉林市| 武冈市| 县级市| 巴马| 保德县| 和静县| 板桥市| 陈巴尔虎旗| 金华市| 曲阳县| 积石山| 兰州市| 雅江县| 宁陵县| 惠安县| 土默特左旗| 安阳县| 中宁县| 灵璧县| 襄汾县| 来宾市| 南陵县| 太仆寺旗| 南木林县| 大邑县| 玉田县| 中方县| 苏州市| 靖西县| 永嘉县| 吉首市| 洛隆县| 海宁市|