JS事件的捕獲和冒泡階段

JS事件的捕獲和冒泡階段

這里介紹兩個事件模型:IE事件模型與DOM事件模型

  1. IE內核瀏覽器的事件模型是冒泡型事件(沒有捕獲事件過程),事件句柄的觸發順序是從ChildNode到ParentNode。
 <div id="ancestor"> <button id="child"> child</button> <button id="child2"> child2</button> 
</div> 
  1. 以上的HTML代碼在IE內核下,事件是這樣傳播的:

    1、Button#child;
    2、div#ancestor;
    3、Body;
    4、Document

    DOM標準的瀏覽器事件是:捕獲事件和冒泡事件。

    捕獲事件過程

    1、Window
    2、Document
    3、Body
    4、Div#ancestor
    5、Button#child

    冒泡事件過程

    6、Div#ancestor
    7、Body
    8、Document
    9、Window

當開發者在一個元素上注冊了事件后,這個事件的響應順序是從window(最頂層)開始一級一級的向下傳播,然后到了該元素后事件捕獲過程結束,事件開如冒泡,一級一級向父層元素冒泡(請注意第6步)。

當然,開發者可以很輕松的決定DOM標準的瀏覽器中的事件需要在哪個傳播過程觸發。

事件的注冊機制

DOM標準的瀏覽器事件注冊方法是通過addEventListener方法注冊,而IE內核的瀏覽器則是通過attachEvent方法注冊。

addEventListener

addEventListener方法帶有三個參數,分別是:eventType、handler、useCapture。

a. eventType不帶有on字符串;
b. handler參數是一個事件句柄,這個函數或方法帶有一個事件對象參數;
c. useCapture參數決定了事件句柄觸發在哪種事件傳播階段,如果useCapture為true則為捕獲階段,反之則為冒泡階段。

// html文件<div id="ancestor"> <button id="child"> child</button> <button id="child2"> child2</button> 
</div> 
// js代碼
let ancestorHandler = function (e){ console.log("div");
}
let childHandler = function (e){ console.log("button");
};document.querySelector('#ancestor').addEventListener('click',ancestorHandler,false);//注意第三個參數 ,注冊了一個在冒泡階段觸發的事件句柄document.querySelector('#child').addEventListener('click',childHandler,true);//注意第三個參數 ,注冊了一個在捕獲階段的事件句柄

輸出結果:

"button"
"div"

當用戶在這個DIV元素上點擊時,事件的執行順序是childHandler、ancestorHandler。

原因:按鈕的事件是在捕獲階段觸發的,也就是從上到下,而DIV的事件是注冊在冒泡階段,也就是點擊了這個按鈕開始從這個按鈕的位置往上冒泡。

其中useCapture我們設置了true,我們選擇在捕獲階段處理該handler。
其中useCapture我們設置了false,我們選擇在冒泡階段處理該handler。

我們來看一下事件的流程:

  1. 當用戶點擊DIV上的元素時,觸發監聽事件
  2. 執行childHandler
  3. 執行ancestorHandler

原因:按鈕的事件是在捕獲階段觸發的,也就是從上到下的順序,而DIV的事件是注冊在冒泡階段,也就是在點擊了這個按鈕button之后,從這個位置往上冒泡。

阻止事件的冒泡:

DOM事件對象提供了stopPropagation方法用于阻止事件流。

var ancestorHandler = function (e){ //...... 
}, 
childHandler = function (e){ e.stopPropagation(); //...... 
}; 

以上代碼在childHandler函數中添加了e.stopPropagation()代碼片段,它將阻止事件流,事件流包括捕獲階段及冒泡階段的事件流。

再修改上面的代碼如下:

let ancestorHandler = function (e){ console.log("div");
}
let childHandler = function (e){ console.log("button");
};
document.querySelector('#ancestor').addEventListener('click',ancestorHandler,true);//注意第三個參數 
document.querySelector('#child').addEventListener('click',childHandler,true);//注意第三個參數 

輸出結果:

// 點擊child
"div"
"button"
// 點擊child2
"div"

分析一下上面的代碼
點擊child按鈕

1.當用戶點擊div內的child按鈕元素時,將會依次觸發ancestorHandler、childHandler函數
2.原因是我們將div#ancestor的事件注冊到捕獲階段了,也就是從上到下。
3.用戶點擊div區域,僅僅先觸發了ancestorHandler函數,因為事件流被阻止了
4.處理完ancestorHandler事件之后,再捕獲到child點擊事件,然后執行childHandler函數

點擊child2按鈕

1.當用戶點擊child按鈕時,會觸發點擊div內的元素觸發后的handler,也就是ancestorHandler函數
2.然后輸出div

removeEventListener

刪除監聽事件處理函數的方法,主要是針對移除 addEventListener() 方法添加的監聽事件。

removeEventListener同樣帶有三個參數,分別是:eventType、handler、useCapture,和addEventListener是同樣的。

// 向 <div> 元素添加事件句柄
document.getElementById("myDIV").addEventListener("mousemove", myFunction, false);// 移除 <div> 元素的事件句柄
document.getElementById("myDIV").removeEventListener("mousemove", myFunction, false);

示例:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>vincent</title>
<style>
#myDIV 
{background-color: coral;border: 1px solid;padding: 50px;color: white;
}
</style>
</head>
<body><div id="myDIV"> div 元素添加了  onmousemove 事件句柄,在你移動鼠標時會顯示隨機數。<p>點擊按鈕移除 DIV 的事件句柄。</p><button onclick="removeHandler()" id="myBtn">點我</button>
</div>
<p id="demo"></p>
<script>
document.getElementById("myDIV").addEventListener("mousemove", myFunction);
function myFunction() 
{document.getElementById("demo").innerHTML = Math.random();
}
function removeHandler() 
{document.getElementById("myDIV").removeEventListener("mousemove", myFunction);
}
</script></body>
</html>

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/536129.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/536129.shtml
英文地址,請注明出處:http://en.pswp.cn/news/536129.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

2016: C語言實驗——打印金字塔

2016: C語言實驗——打印金字塔 Description 輸入n值&#xff0c;打印下列形狀的金字塔&#xff0c;其中n代表金字塔的層數。 Input 輸入只有一個正整數n。 Output 打印金字塔圖形&#xff0c;其中每個數字之間有一個空格。 Sample Input 3 Sample Output 11 2 1 1 2 …

Anuglar中正確導入RxJS庫

Anuglar中正確導入RxJS庫 目前Angular2中的已經內建支持RxJS,所以我們在使用的時候可以直接導入使用了。 理解操作符導? 在使用創建依賴于 RxJS 組件,服務,指令等等時, 你可能遇到處理運算符導?的問 題。 在項?中引?操作符最主要的?式像下?這樣導?: import rxj…

1495: 蛇行矩陣

1495: 蛇行矩陣 Description 蛇形矩陣是由1開始的自然數依次排列成的一個矩陣上三角形。 Input 本題有多組數據&#xff0c;每組數據由一個正整數N組成。&#xff08;N不大于100&#xff09; Output 對于每一組數據&#xff0c;輸出一個N行的蛇形矩陣。兩組輸出之間不要額…

遞歸基礎之N皇后問題

遞歸基礎之N皇后問題 Description 在nn 格的棋盤上放置彼此不受攻擊的n 個皇后。按照國際象棋的規則&#xff0c;皇后可以攻擊與之 處在同一行或同一列或同一斜線上的棋子。n后問題等價于在nn格的棋盤上放置n個皇后&#xff0c; 任何2 個皇后不放在同一行或同一列或同一斜線上…

X86和X86_64和AMD64的由來

為什么叫X86和X86_64和AMD64 為什么大家叫x86為32位系統呢 相信大家在大學里面有很多人都玩過8086&#xff08;微處理器&#xff09;&#xff0c;這是一個可編程的系統&#xff0c;他是由intel開發的&#xff0c;英特爾出了劃時代的8086之后&#xff0c;后來使用該架構出了80…

回爐-熄燈問題

進來突然意識到算法的重要性&#xff0c;可惜已經沒有充足的時間去進行專業的訓練了&#xff0c;只能慢慢擠時間做幾個題練習一下聊以安慰&#xff0c;希望能多堅持幾天吧&#xff0c;奉勸各位想學算法的同學一定要趁早啊。 poj1222 解析見郭煒老師的程序設計與算法&#xff…

ngrx初識

ngrx初識 在使用之前需要安裝ngrx npm install @ngrx/store --save 或者 yarn add @ngrx/store ngrx/store:保存了ReduxAPI的核心概念,使用RxJS擴展的Redux實現。使用可觀察對象來簡化了監聽事件的訂閱等操作。 dispatch&reducer&state dispatcher,reducer,state…

回爐-特殊密碼鎖

題目&#xff1a;特殊密碼鎖 001:特殊密碼鎖 描述 有一種特殊的二進制密碼鎖&#xff0c;由n個相連的按鈕組成&#xff08;n<30&#xff09;&#xff0c;按鈕有凹/凸兩種狀態&#xff0c;用手按按鈕會改變其狀態。 然而讓人頭疼的是&#xff0c;當你按一個按鈕時&#x…

Angular的NgModule

Angular的NgModule NgModule作為Angular模塊的核心,也是組織者,官方有很長的文檔來介紹他,包括每一個API。 @NgModule文件的定義方式 import { BrowserModule } from @angular/platform-browser; import { NgModule } from @angular/core;import { AppComponent } from ./ap…

回爐-撥鐘問題

題目&#xff1a;撥鐘問題 1166:撥鐘問題 描述 有9個時鐘&#xff0c;排成一個3*3的矩陣。 |-------| |-------| |-------| | | | | | | | |---O | |---O | | O | | | | | | | |-------| |-------| …

Ubuntu擴展觸摸屏觸控錯位修復

Ubuntu擴展觸摸屏觸控錯位修復 當我們ubuntu外接一個觸摸顯示器的時候&#xff0c;會發現觸摸擴展屏幕&#xff0c;發現操控的是主屏幕&#xff0c;我寫了一個腳本去修復。 #! /bin/bash #------------------------------------------------------------------------------ #…

目標檢測與分割總結

目標檢測最常用的三個模型&#xff1a;Faster R-CNN、SSD和YOLO Faster R-CNN架構 在Faster RCNN中&#xff0c;候選框是經過RPN產生的&#xff0c;然后再把各個“候選框”映射到特征圖上&#xff0c;得到RoIs。 Faster R-CNN步驟&#xff1a; (1) 由輸入圖片產生的區域候選…

shell腳本單詞去重多個文件

shell腳本單詞去重多個文件 例如要求如下&#xff1a; 有多個txt文件&#xff0c;每個文件內有多行單詞 中間為英文的”,”&#xff0c;或者中文的”&#xff0c;”逗號作為分隔符。 world,世界 set&#xff0c;設置 good,好&#xff0c;商品 .... 將這些文件匯總去除重復…

win10連接煙臺大學校園網

第一步 右鍵網絡圖標&#xff0c;打開網絡管理中心 第二步&#xff1a; 設置添加新的網絡&#xff0c;方法步驟如下&#xff1a; 第三步&#xff1a;新建VPN連接&#xff0c;注意協議為L2TP 第四步&#xff1a; 第五步&#xff1a; 第六步&#xff1a; 創建結束后進入更…

Angular國際化方案

Angular國際化方案 首先和大家推薦一個xlf文件的操作工具,支持合并和編輯功能,github,到release界面下載。 對于Angular國際化,官方提供了i18n方案,也就是標簽的方式,通過angular CLI來識別。國際化方案必須在編譯前定義下來,所以不能動態翻譯。也就是當有人切換語言時,…

模擬退火算法(TSP問題)

模擬退火算法解決TSP問題 算法思想 模擬退火算法&#xff08;Simulate Anneal&#xff0c;SA&#xff09;是一種通用概率演算法&#xff0c;用來在一個大的搜尋空間內找尋命題的最優解 模擬退火算法來源于固體退火原理&#xff0c;將固體加溫至充分高&#xff0c;再讓其徐徐…

2-docker 安裝

2-docker 安裝 Ubuntu 安裝 由于 apt 源使用 HTTPS 以確保軟件下載過程中不被篡改。因此&#xff0c;我們首先需要添加使用 HTTPS 傳輸的軟件包以及 CA 證書。 $ sudo apt-get update$ sudo apt-get install \apt-transport-https \ca-certificates \curl \gnupg-agent \sof…

U-Net++粗略解釋

Paper&#xff1a;UNet: A Nested U-Net Architecture for Medical Image Segmentation u-net網絡的基本拓撲結構 目前最先進的圖像分割模型是各種個同樣的 encoder-decoder架構&#xff0c;他們具有一個關鍵的相似性&#xff1a;skip connections&#xff0c;它可以將編碼器…

Spring中的組合模式

組合模式是一種對象設計模式&#xff0c;它允許你將對象組合成樹形結構以表示“部分-整體”的層次結構&#xff0c;使得客戶端以統一的方式處理單個對象和對象的組合。在Spring框架中&#xff0c;組合模式被廣泛應用&#xff0c;讓我們深入分析一下。 在Spring中&#xff0c;組…

Docker+Nginx部署Angular

DockerNginx部署Angular 在部署Angular生產環境之前&#xff0c;需要電腦已經安裝docker。 添加Dockerfile 在已經完成的Angular項目的項目根目錄下添加Dockerfile文件。 Dockerfile文件內容&#xff1a; FROM nginx:1.11-1.11-alpine COPY index.html /usr/share/nginx/ht…