欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript 事件捕獲冒泡與捕獲詳情

 更新時間:2021年11月10日 08:49:19   作者:四冥  
這篇文章主要介紹了JavaScript事件捕獲冒泡與捕獲,文章主要圍繞JavaScript事件捕獲冒泡與捕獲展開詳細內容,需要的朋友可以參考一下,希望對你有所幫助

一、事件流

JavaScript中,事件流指的是DOM事件流。

1、概念

事件的傳播過程即DOM事件流。
事件對象在 DOM 中的傳播過程,被稱為“事件流”。
舉個例子:開電腦這個事,首先你是不是得先找到你的電腦,然后找到你的開機鍵,最后用手按下開機鍵。完成開電腦這個事件。這整個流程叫做事件流。

2、DOM事件流

DOM事件,也是有一個流程的。從事件觸發(fā)開始到事件響應是有三個階段。

  • 事件捕獲階段
  • 處于目標階段
  • 事件冒泡階段

上面例子中,開電腦這個事件的過程就像JavaScript中的事件流,找開機鍵這個過程就是 事件捕獲 的過程,你找到開機鍵后,然后用手按開機鍵,這個選擇用手去按的過程就是 處于目標階段 按下開機按鈕,電腦開始開機這也就是 事件的冒泡。 順序為先捕獲再冒泡。

了解了事件源,讓我們看看它的三個過程吧!

事件捕獲:

注:由于事件捕獲不被舊版本瀏覽器(IE8 及以下)支持,因此實際中通常在冒泡階段觸發(fā)事件處理程序。

事件捕獲處于事件流的第一步,
DOM事件觸發(fā)時(被觸發(fā)DOM事件的這個元素被叫作事件源),瀏覽器會從根節(jié)點開始 由外到內 進行事件傳播。即事件從文檔的根節(jié)點流向目標對象節(jié)點。途中經過各個層次的DOM節(jié)點,最終到目標節(jié)點,完成事件捕獲。

目標階段:

當事件到達目標節(jié)點的,事件就進入了目標階段。事件在目標節(jié)點上被觸發(fā)。
就是事件傳播到觸發(fā)事件的最底層元素上。

事件冒泡:

事件冒泡與事件捕獲順序相反。事件捕獲的順序是從外到內,事件冒泡是從內到外。
當事件傳播到了目標階段后,處于目標階段的元素就會將接收到的時間向上傳播,就是順著事件捕獲的路徑,反著傳播一次,逐級的向上傳播到該元素的祖先元素。直到window對象。

看一個例子,點擊 box3 會將 box2 與 box1 的點擊事件觸發(fā)。

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>JavaScript 事件冒泡</title>
</head>
<style type="text/css">
    #box1 { background: blueviolet;}
    #box2 {background: aquamarine;}
    #box3 {background: tomato;}
    div { padding: 40px; margin: auto;}
</style>

<body>
    <div id="box1">
        <div id="box2">
            <div id="box3"></div>
        </div>
    </div>
    <script>
        window.onload = function () {
            const box1 = document.getElementById('box1')
            const box2 = document.getElementById('box2')
            const box3 = document.getElementById('box3')
            box1.onclick = sayBox1;
            box2.onclick = sayBox2;
            box3.onclick = sayBox3;
            function sayBox3() {
                console.log('你點了最里面的box');
            }
            function sayBox2() {
                console.log('你點了最中間的box');
            }
            function sayBox1() {
                console.log('你點了最外面的box');
            }
        }
    </script>
</body>

</html>


這個時候 click 捕獲的傳播順序為:
window -> document -> <html> -> <body> -> <div #box1> -> <div #box2> -> <div #box3>
這個時候 click 冒泡的傳播順序為:
<div #box3> -> <div #box2> -> <div #box1> -> <body> -> <html> -> document -> window

現(xiàn)代瀏覽器都是從 window 對象開始捕獲事件的,冒泡最后一站也是 window 對象。而 IE8 及以下瀏覽器,只會冒泡到 document 對象。
事件冒泡:是由元素的 HTML 結構決定,而不是由元素在頁面中的位置決定,所以即便使用定位或浮動使元素脫離父元素的范圍,單擊元素時,其依然存在冒泡現(xiàn)象。

現(xiàn)在我們知道了事件流的三個階段后,那我們可以利用這個特性做什么呢?

二、事件委托

設想這樣一個場景,當你有一堆的<li>標簽在一個<ul>標簽下,需要給所有的<li>標簽綁定onclick事件,這個問題我們可以用循環(huán)解決,但還有沒有更簡便的方式呢?
我們可以給這些<li>共同的父元素<ul>添加onclick事件,那么里面的任何一個<li>標簽觸發(fā)onclick事件時,都會通過冒泡機制,將onclick事件傳播到<ul>上,進行處理。這個行為叫做事件委托, <li>利用事件冒泡將事件委托到<ul>上。
也可以利用事件捕獲進行事件委托。用法是一樣的,只是順序反了。

  <ul id="myUl">
    <li>item 1</li>
    <li>item 2</li>
    <li>item 3</li>
    ...
  </ul>


可能還是有點不好理解,簡單來說,就是利用事件冒泡,將某個元素上的事件委托給他的父級。

舉個生活中的例子,雙十一快遞到了,需要快遞小哥送快遞一般是挨家挨戶送貨上門,這樣效率慢,小哥想了個辦法,把一個小區(qū)的快遞都放在小區(qū)里面的快遞驛站,進行送快遞的事件委托,小區(qū)的收件人能通過取件碼去快遞驛站領取到自己的快遞。
在這里,快遞小哥送快遞就是一個事件,收件人就是響應事件的元素,驛站就相當于代理元素,收件人憑著收獲碼去驛站里面領快遞就是事件執(zhí)行中,代理元素判斷當前響應的事件匹配該觸發(fā)的具體事件。

可是這樣做有什么好處呢?

1、事件委托的優(yōu)點

事件委托有兩個好處

  • 減少內存消耗
  • 動態(tài)綁定事件

減少內存消耗,優(yōu)化頁面性能

JavaScript中,每個事件處理程序都是對象,是對象就會占用頁面內存,內存中的對象越多,頁面的性能當然越差,而且DOM的操作是會導致瀏覽器對頁面進行重排和重繪(這個不清楚的話,小伙伴可以了解頁面的渲染過程),過多的DOM操作會影響頁面的性能。性能優(yōu)化主要思想之一就是為了最小化的重排和重繪也就是減少DOM操作。

在上面給<li>標簽綁定onclick事件的例子中,使用事件委托就可以不用給每一個<li>綁定一個函數(shù),只需要給<ul>綁定一次就可以了,當li的數(shù)量很多時,無疑能減少大量的內存消耗,節(jié)約效率。

動態(tài)綁定事件:

如果子元素不確定或者動態(tài)生成,可以通過監(jiān)聽父元素來取代監(jiān)聽子元素。
還是上面在<li>標簽綁定onclick事件的例子中, 很多時候我們的這些<li>標簽的數(shù)量并不是固定的,會根據用戶的操作對一些<li>標簽進行增刪操作。在每次增加或刪除標簽都要重新對新增或刪除元素綁定或解綁對應事件。

可以使用事件委托就可以不用給每一個<li>都要操作一遍,只需要給<ul>綁定一次就可以了,因為事件是綁定在<ul>上的, <li>元素是影響不到<ul>的 ,執(zhí)行到<li>元素是在真正響應執(zhí)行事件函數(shù)的過程中去匹配的,所以使用事件委托在動態(tài)綁定事件的情況下是可以減少很多重復工作的。

我們知道了事件委托的優(yōu)點,那么該如何使用呢?

2、事件委托的使用

事件委托的使用需要用的addEventListener()方法,事件監(jiān)聽。
方法將指定的監(jiān)聽器注冊到調用該函數(shù)的對象上,當該對象觸發(fā)指定的事件時,指定的回調函數(shù)就會被執(zhí)行。

用法:

element.addEventListener(eventType, function, useCapture);


參數(shù) 必/選填 描述
eventType 必填 指定事件的類型。
function 必填 指定事件觸發(fā)后的回調函數(shù)。
useCapture 選填 指定事件是在捕獲階段執(zhí)行還是在冒泡階段執(zhí)行。

第三個參數(shù) useCapture 是個布爾類型,默認值為false

  • true - 表示事件在捕獲階段執(zhí)行執(zhí)行
  • false- 表示事件在冒泡階段執(zhí)行執(zhí)行

看下面例子:

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>JavaScript 事件委托</title>
</head>

<body>

  <ul>
    <li>item 1</li>
    <li>item 2</li>
    <li>item 3</li>
    <li>item 4</li>
  </ul>

  <script>
    const myUl = document.getElementsByTagName("ul")[0];

    myUl.addEventListener("click", myUlFn);

    function myUlFn(e) {
      if (e.target.tagName.toLowerCase() === 'li') { // 判斷是否為所需要點擊的元素
        console.log(`您點擊了${e.target.innerText}`);
      }
    }

  </script>
</body>

</html>

注意:這是一般的事件委托方法,但是這種寫法有問題,就是當_<li>_中還有子元素時,點擊這個子元素就不會進行觸發(fā)事件。這個問題是一個坑。

事件冒泡有時候確實很有用,但是有時候也討人煩,當你不需要它的時候能不能取消掉呢?

三、禁止事件冒泡與捕獲

注意:并不是所有事件都會冒泡,比如focus,blur,change,submit,reset,select等。

禁止冒泡和捕獲可以用到方法stopPropagation()。
stopPropagation()起到阻止捕獲和冒泡階段中當前事件的進一步傳播。
這是阻止事件的冒泡方法,進行冒泡,但是默認事件任然會執(zhí)行,當你調用了這個方法后。
如果點擊一個a標簽,這個a標簽會進行跳轉。

使用起來也很簡單,沒有返回值也沒有參數(shù)。

event.stopPropagation();


請看下面例子,這個例子實在上文事件冒泡例子基礎上稍加修改得到的

    <div id="box1">
        <div id="box2">
            <div id="box3"></div>
        </div>
    </div>
    <script>
        const box1 = document.getElementById('box1')
        const box2 = document.getElementById('box2')
        const box3 = document.getElementById('box3')
        box1.onclick = sayBox1;
        box2.onclick = sayBox2;
        box3.onclick = sayBox3;
        function sayBox3() {
            console.log('你點了最里面的box');
        }
        function sayBox2(e) {
            console.log('你點了最中間的box');
            e.stopPropagation(); //禁止事件捕獲和冒泡
        }
        function sayBox1() {
            console.log('你點了最外面的box');
        }
    </script>

當事件冒泡到box2時調用了在函數(shù)sayBox2,調用了e.stopPropagation(); 就停止冒泡了。

到此這篇關于JavaScript 事件捕獲冒泡與捕獲詳情的文章就介紹到這了,更多相關JavaScript事件捕獲冒泡與捕獲內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

四、參考文獻

MDN中文版 https://developer.mozilla.org/zh-CN/
知乎 https://zhuanlan.zhihu.com/p/26536815

相關文章

  • JavaScript函數(shù)柯里化

    JavaScript函數(shù)柯里化

    這篇文章主要介紹了JavaScript函數(shù)柯里化,柯里化即Currying是把接受多個參數(shù)的函數(shù)變換成接受一個單一參數(shù)函數(shù),并且返回接受余下的參數(shù)且返回結果的新函數(shù)的技術,下面文章詳細內容,需要的朋友可以參考一下
    2021-11-11
  • 微信小程序 Toast自定義實例詳解

    微信小程序 Toast自定義實例詳解

    這篇文章主要介紹了微信小程序 Toast自定義實例詳解的相關資料,需要的朋友可以參考下
    2017-01-01
  • JavaScript設計模式之命令模式和狀態(tài)模式詳解

    JavaScript設計模式之命令模式和狀態(tài)模式詳解

    這篇文章主要為大家介紹了JavaScript設計模式之命令模式和狀態(tài)模式詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • JavaScript前端學算法題解LeetCode最大重復子字符串

    JavaScript前端學算法題解LeetCode最大重復子字符串

    這篇文章主要為大家介紹了JavaScript前端學算法題解LeetCode最大重復子字符串,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • JS網頁repaint與reflow?的區(qū)別及優(yōu)化方式

    JS網頁repaint與reflow?的區(qū)別及優(yōu)化方式

    這篇文章主要為大家介紹了JS網頁repaint與reflow?的區(qū)別及優(yōu)化方式,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • Javascript閉包使用場景原理詳細

    Javascript閉包使用場景原理詳細

    這篇文章主要介紹了Javascript閉包的使用場景,  由于在Javascript語言中,只有函數(shù)內部的子函數(shù)才能讀取局部變量,閉包就是能夠讀取其他函數(shù)內部變量的函數(shù)。所以,在本質上,閉包就是將函數(shù)內部和函數(shù)外部連接起來的一座橋梁,下面一起進入文化在哪個了解文章內容
    2021-11-11
  • 微信小程序 實戰(zhàn)程序簡易新聞的制作

    微信小程序 實戰(zhàn)程序簡易新聞的制作

    這篇文章主要介紹了微信小程序 實戰(zhàn)程序簡易新聞的制作的相關資料,需要的朋友可以參考下
    2017-01-01
  • 學習筆記編寫vue的第一個程序

    學習筆記編寫vue的第一個程序

    這篇文章主要介紹了學習筆記vue的第一個程序,其中非常詳細的為大家講解了vue程序的創(chuàng)建步驟,有需要的朋友可以學習下,希望可以有所幫助
    2021-08-08
  • JS 基本概念詳細介紹

    JS 基本概念詳細介紹

    這篇文章主要介紹JS 基本概念,對于初學者來說,Javascript 乍一看似乎很容易,因為它的類似于 C 的語法,但不管它的運行方式如何,對語言 (ESNext) 及其框架所做的不斷變化可能會讓初學者不知所措。下面我們就來看JS 初學者怎么入門吧
    2021-10-10
  • 微信小程序的生命周期的詳解

    微信小程序的生命周期的詳解

    這篇文章主要介紹了微信小程序的生命周期的詳解的相關資料,希望通過本文能幫助到大家,需要的朋友可以參考下
    2017-10-10

最新評論