顯示具有 event flow 標籤的文章。 顯示所有文章
顯示具有 event flow 標籤的文章。 顯示所有文章

2022年8月31日 星期三

DOM - 2 Event 的特殊處理 - 停止event預設動作 - 停止往上冒泡 -bubble,catch

目的: 停止event預設動作 - 停止往上冒泡處理說明:1> Label 的event flow 為 bubble 方式時

            2> 觸發 lbl.onclick event後 , console 顯示 "lbl click"

                 瀏覽器將 click event  自動往下傳, 即傳給 checkbox.click event

            3> 因 checkbox event 為 bubble 方式,所以又往上傳給 lbl 

                即觸發 lbl.onclick event , concole 又顯示 "lbl click"

--> 即 lbl.onclick event 被觸發兩次


一.要阻擋事件向上冒泡傳遞:

--> event.stopPropagation()



<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="src/style.css" />
  </head>
  <body>
    <h1>Hi friend, try edit me!</h1>
    <label class="lbl">
      Label <input type="checkbox" name="chkbox" id="chkbox" />
    </label>
    // label

    <script>
      var lbl = document.querySelector('.lbl');
      var chkbox = document.querySelector('#chkbox');

      lbl.addEventListener('click', function (e) {
        console.log('lbl click');
      }, false);

      chkbox.addEventListener('click', function (e) {
        console.log('chkbox click');
      }, false);

    </script>

    <script src="src/script.js"></script>
  </body>
</html>

-->

     chkbox.addEventListener('click', function (e) {
        console.log('chkbox click');
         e.stopPropagation();
      }, false);





二.不執行預設動作, 只執行目前動作( console.log("google") )



<a id="link" href="https://www.google.com">Google</a>

var link = document.querySelector('#link'); 

// 在 evend handler 加上 e.preventDefault(); 
link.addEventListener('click', function (e) { 
e.preventDefault(); 
console.log('Google!'); 
}, false);

2022年8月30日 星期二

DOM -1 Event 的處理機制 - bubble -catch -eventflow

目的: 了解 Web  DOM的 event 處理 機制

處理說明:   1> catch 時, 由上而下 (Document --> html --> body --> table --> tr --> td --> div)

                    2> bubble時, 由下而上(div-->td--> tr--> table --> body --> html --> Document)

-->  DOM 兩種機制 (catch/bubble) 均有, 可分別設定 catch / bubble 的 event handler

參考原始網址: https://ithelp.ithome.com.tw/articles/10191970

- 重新認識 JavaScript: Day 14 事件機制的原理



而事件流程 (Event Flow) 指的就是「網頁元素接收事件的順序」。

事件流程可以分成兩種機制:

  • 事件冒泡 (Event Bubbling)
  • 事件捕獲 (Event Capturing)

假設現在的事件是點擊上圖中藍色的 <td>

那麼當 td 的 click 事件發生時,會先走紅色的 「capture phase」:

  1. Document
  2. <html>
  3. <body>
  4. <table>
  5. <tbody>
  6. <tr>
  7. <td> (實際被點擊的元素)

由上而下依序觸發它們的 click 事件。

然後再繼續執行綠色的 「bubble phase」,反方向由 <td> 一路往上傳至 Document,整個事件流程到此結束。

Ex:  DOM的實作案例

<div>
    <div id="parent">父元素      
          <div id="child">子元素</div>
     </div>
</div>


// 父元素
var parent = document.getElementById('parent');
// 子元素
var child = document.getElementById('child');

// 透過 addEventListener 指定事件的綁定
// 第三個參數 true / false 分別代表捕獲/ 冒泡 機制

parent.addEventListener('click', function () {
  console.log('Parent Capturing');
}, true);  //capture 機制 event hadler

parent.addEventListener('click', function () {
  console.log('Parent Bubbling');
}, false); //bubble 機制 event hadler


child.addEventListener('click', function () {
  console.log('Child Capturing');
}, true);

child.addEventListener('click', function () {
  console.log('Child Bubbling');
}, false);

-->

當我點擊的是「子元素」的時候,透過 console.log 可以觀察到事件觸發的順序為:
       "Parent Capturing"
       "Child Capturing"
       "Child Bubbling"
       "Parent Bubbling"

由此可知,點擊子元素的時候,父層的 Capturing 會先被觸發,然後再到子層內部的 Capturing 或 Bubbling 事件。 最後才又回到父層的 Bubbling 結束。

子層的 Capturing 或 Bubbling 誰先誰後呢?
要看你程式碼的順序而定。

子層若是 Capturing 在 Bubbling 前面:

child.addEventListener('click', function () { console.log('Child Capturing'); }, true); child.addEventListener('click', function () { console.log('Child Bubbling'); }, false);

--> 子層觸發順序
"Child Capturing" "Child Bubbling"

-->
addEventListener() 基本上有三個參數,分別是「事件名稱」、「事件的處理器」(事件觸發時執行的 function),以及一個「Boolean」值,由這個 Boolean 決定事件是以「捕獲」或「冒泡」機制執行,若不指定則預設為「冒泡」。
true/false : catch/bubble


Bubble 及 Catch event flow