1. 程式人生 > 其它 >事件冒泡、事件捕獲、事件委託

事件冒泡、事件捕獲、事件委託

首先介紹個方法

element.addEventListener(event, function, useCapture)

addEventListener方法原生的JS方法,用來為一個特定的元素繫結一個事件處理函式。

三個引數分別:

  1. event: 事件型別
  2. function: 事件處理函式
  3. useCapture: 控制事件階段

第三個引數useCapture是boolean型別:

預設是false,表示在事件冒泡的階段呼叫事件處理函式,

如果設定為 true,則表示在事件捕獲的階段呼叫事件處理函式。

事件冒泡

當一個元素接收到事件的時候 會把他接收到的事件傳給自己的父級,一直到window。

即指子元素的事件向父元素傳遞的過程。

例如:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>事件冒泡</title>
</head>
<body>
<div>
    <p>
        <button id="b1">點我</button>
    </p>
</div>

<script src="https://code.jquery.com/jquery-3.3.1.min.js"
></script> <script> /* 因為監聽函式addEventListener第三個引數預設為false 因此直接使用click、focus等函式,預設就是冒泡事件 */ $('div').click(function () { console.log('我是div標籤'); }); $('p').click(function () { console.log('我是一個p標籤'); }); // $('#b1')[0] JQ原生轉DOM元素 $(
'#b1')[0].addEventListener('click', function () { console.log('我是那個按鈕!'); }, false) </script> </body> </html>

當點選按鈕後,事件會從子元素(button)一直傳遞到父元素window,結果:

事件捕獲

事件捕獲與事件冒泡相反,事件的傳遞從父元素向下傳遞到子元素。

即指父元素的事件向子元素傳遞的過程。

例如:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>事件捕獲</title>
</head>
<body>
<div>
    <p>
        <button id="b1">點我</button>
    </p>
</div>

<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
    // 設定為true代表事件捕獲
    $('div')[0].addEventListener('click', function () {
        console.log('我是div標籤');
    }, true);

    $('p')[0].addEventListener('click', function () {
        console.log('我是一個p標籤');
    }, true);

    // $('#b1')[0] JQ原生轉DOM元素
    $('#b1')[0].addEventListener('click', function () {
        console.log('我是那個按鈕!');
    }, true)
</script>
</body>
</html>

當點選按鈕後,事件會從父元素window一直傳遞到子元素(button),結果:

事件冒泡與事件捕獲的關係

即:事件捕獲先發生,再到事件冒泡

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>事件冒泡與捕獲</title>
</head>
<body>
<div>
    <p>
        <button id="b1">點我</button>
    </p>
</div>

<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
    // 事件捕獲
    $('div')[0].addEventListener('click', function () {
        console.log('我是div標籤');
    }, true);
    // 事件冒泡
    $('div')[0].addEventListener('click', function () {
        console.log('我是div標籤');
    }, false);

    $('p')[0].addEventListener('click', function () {
        console.log('我是一個p標籤');
    }, true);
    $('p')[0].addEventListener('click', function () {
        console.log('我是一個p標籤');
    }, false);

    $('#b1')[0].addEventListener('click', function () {
        console.log('我是那個按鈕!');
    }, true)
    $('#b1')[0].addEventListener('click', function () {
        console.log('我是那個按鈕!');
    }, false)
</script>
</body>
</html>

當點選按鈕後,先發生事件捕獲,再發生事件冒泡,結果:

事件委託

事件委託是通過事件冒泡的原理,利用父標籤去捕獲子標籤的事件。

語法:
$("table").on("click", "button", function () {
  // JS程式碼
})

解釋:給table繫結一個點選事件,但是是通過button觸發的。

注意事項1:
像click、keydown等DOM中定義的事件,我們都可以使用`.on()`方法來繫結事件,但是`hover`這種jQuery中定義的事件就不能用`.on()`方法來綁定了,
也就是說hover()方法不能直接使用事件委託,想使用事件委託的方式繫結hover事件處理函式,可以參照如下程式碼分兩步繫結事件:

$('ul').on('mouseenter', 'li', function() {//繫結滑鼠進入事件
    $(this).addClass('hover');
});
$('ul').on('mouseleave', 'li', function() {//繫結滑鼠劃出事件
    $(this).removeClass('hover');
});

注意事項2
關於this:誰觸發這個事件,this就指向誰。
例如:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
</head>
<body>
<div id="div">
    <p id="p">
        <input type="button" value="點我" id="btn">
    </p>
</div>

<script type="text/javascript">
    $("#div").click(function () {
        //點選按鈕,經過事件冒泡,觸發這個事件
        //此時this是代表div的,雖然點選的是那個按鈕
        //但是實際上是經過冒泡後,div自己觸發的這個事件,所有this是div
        console.log(this);
    });

    //任意註釋一個script標籤測試另一個標籤
    
    $("#div").on("click", "#btn", function () {
        //事件委託,給div綁定了一個事件,點選按鈕觸發這個事件
        //此時this是代表按鈕btn的,雖然繫結的事件是div
        //但是觸發這個事件的是btn,所以this是btn
        console.log(this);
    })

</script>
</body>
</html>