1. 程式人生 > >淺談Event Flow、Process、Method及其Applications

淺談Event Flow、Process、Method及其Applications

事件流動(Event Flow):

  DOM(文件物件模型)結構是一個樹型結構,當一個HTML元素產生一個事件時,該事件會在元素節點與根結點之間的路徑傳播,路徑所經過的結點都會收到該事件,這個傳播過程可稱為DOM事件流。DOM事件流最獨特的性質是,文字節點也觸發事件(在IE中不會),當滑鼠單擊“單擊此文字”文字時會觸發click事件,該事件的捕獲階段最先開始,從Document節點開始逐漸向下傳播,直到“單擊此文字”文字節點,事件進入目標階段,在目標階段結束之後,事件由“單擊此文字”文字節點開始事件的冒泡階段,直到Document節點為止。所以說,DOM事件不單單隻會在一個Element上觸發,它還會流向其他Element。事件的流動通常會經歷這麼三個階段;

     冒泡型事件流:事件的傳播是從最特定事件目標到最不特定的事件目標。即從DOM樹的葉子到根。

    捕獲型事件流:事件的傳播的英文從最不特定事件目標到最特定的事件目標。即從DOM樹的根到葉子。

過程(Process):

  事件通過DOM樹傳播。應用程式可以使用該dispatchEvent()方法排程事件物件,並且事件物件將通過DOM事件流確定的DOM樹傳播。

       事件物件被分派到事件目標。但是在傳送開始之前,必須首先確定事件物件的傳播路徑傳播路徑是的有序列表的當前事件的目標

,通過該事件傳遞。該傳播路徑反映了文件的分層樹結構。列表中的最後一項是事件目標,列表中的前面專案稱為目標的祖先,前面的專案作為目標的父項。一旦確定了傳播路徑,事件物件就會經過一個或多個事件階段。有三個事件階段:捕獲階段目標階段泡沫階段。事件物件完成這些階段,如下所述。如果不支援某個階段,或者事件物件的傳播已停止,則將跳過該階段。例如,如果bubbles屬性設定為false,則將跳過氣泡階段,如果stopPropagation()在分派之前呼叫,則將跳過所有階段。

1.捕獲階段(capture phase)

  定義事件物件在事件目標的祖先中上到下順向傳播,從最頂層的defaultView到事件目標的(直系)父元素。

  捕獲階段發生在整個事件流動的開始。在這階段裡事件會從父(主幹)到子(分支)由上往下傳播,被元素一層層地捕獲。

  

2.目標階段(target phase)

  

  定義:事件物件到達事件目標。

3。冒泡階段(bubble phase)

       定義:事件物件會在事件目標的祖先元素裡反向傳播,由開始的父元素到最後的defaultView(document)。

  冒泡階段發生在最後,這也是我們最為熟悉的一個階段。在這階段裡事件會從子(分支)到父(主幹)逆向傳播,看起來像是一個水裡的泡泡往上冒。

方法(Method):

  語法: 
  element.addEventListener(event, function, useCapture) 

  event  必需。描述事件名稱的字串。注意: 不要使用 "on" 字首。例如,使用 "click" 來取代 "onclick"。

  function  必需。描述了事件觸發後執行的函式。 當事件觸發時,事件物件會作為第一個引數傳入函式。 事件物件的型別取決於特定的事件。例如, "click" 事件屬於 MouseEvent(滑鼠事件) 物件。

  useCapture  可選。布林值,指定事件是否 在捕獲或冒泡階段執行。可能值:true - 事件控制代碼在捕獲階段執行  false- 預設。事件控制代碼在冒泡階段執行

應用(Applications):(轉載自:https://blog.csdn.net/qq_30100043/article/details/77186811 )

  

 1 <!doctype html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
 6     <meta http-equiv="X-UA-Compatible" content="ie=edge">
 7     <title>Document</title>
 8     <style>
 9         #wrap {
10             width: 200px;
11             height: 200px;
12             background: orange;
13         }
14         #outer {
15             position: relative;
16             top: 50px;
17             left: 50px;
18             width: 100px;
19             height: 100px;
20             background: #eeddff;
21         }
22         #inner {
23             position: relative;
24             top: 25px;
25             left:25px;
26             width: 50px;
27             height: 50px;
28             background: #44ddff;
29         }
30     </style>
31 </head>
32 <body>
33 <div id="wrap">
34     <div id="outer">
35         <div id="inner"></div>
36     </div>
37 </div>
38 </body>
39 <script>
40     var wrap = document.getElementById('wrap');
41     var outer = document.getElementById('outer');
42     var inner = document.getElementById('inner');
43 
44     wrap.addEventListener('click',function(){
45         alert('789');
46     },false);
47     outer.addEventListener('click',function(){
48         alert('456');
49     },false);
50     inner.addEventListener('click',function(){
51         alert('123');
52     },false);
53     inner.addEventListener('click',function(){
54         alert('inner');
55     },true);
56     wrap.addEventListener('click',function(){
57         alert('wrap');
58     },true);
59     outer.addEventListener('click',function(){
60         alert('outer');
61     },true);
62 </script>
63 </html>

以上程式碼摘自https://segmentfault.com/a/1190000003497939) 

點選檢視此案例,我們會發現,首先是觸發的是捕獲階段的事件,然後再觸發的是冒泡階段的事件。

我們會發現inner的dom物件上繫結的兩個事件,是先彈出的123,然後又彈出的inner。這個是為什麼呢?
這是因為如果當前的dom物件已經處於當前點選位置的最底部了(重點是這裡最底部,如果沒有到最底部,還是和外部的兩個一樣的)。就是說如果這個dom物件是捕獲的終點也是冒泡的起點,它就不區分冒泡捕獲了,只是純粹的綁定了兩個dom事件,所以,這兩個事件就是看誰先繫結的靠前,誰就先實行。。。


(注:以上內容均來源於網上,基本轉自:http://www.cnblogs.com/liuwei-0313/p/9935779.html)