事件高級

一、註冊事件(2種方式)

 

 

二、事件監聽

addEventListener()事件監聽(IE9之後支持)

 

 

eventTarget.addEventListener()方法將指定的監聽器註冊到 eventTarget(目標對象)上,當該對象觸發指定的事件時,就會執行事件處理函數。html

該方法接收三個參數:瀏覽器

  • type: 事件類型字符串,好比click、mouseover ,注意這裏不要帶ondom

  • listener: 事件處理函數,事件發生時,會調用該監聽函數函數

  • useCapture: 可選參數,是-個布爾值,默認是false。學完DOM事件流後,咱們再進一步學習性能

attacheEvent()事件監聽(IE678支持)

 

 

eventTarget.attachEvent()方法將指定的監聽器註冊到 eventTarget(目標對象) 上,當該對象觸發指定的事件時,指定的回調函數就會被執行。學習

該方法接收兩個參數:this

  • eventNameWithOn: 事件類型字符串,好比onclick、 onmouseover,這裏要帶onatom

  • callback: 事件處理函數,當目標觸發事件時回調函數被調用spa

注意: IE8 及早期版本支持3d

<button>傳統註冊事件</button>
<button>方法監聽註冊事件</button>
<button>ie9 attachEvent</button>
<script>
   var btns = document.querySelectorAll('button');
   // 1. 傳統方式註冊事件
   btns[0].onclick = function() {
       alert('hi');
  }
   btns[0].onclick = function() {
           alert('hao a u');
      }
  // 2. 事件偵聽註冊事件 addEventListener
  // (1) 裏面的事件類型是字符串 一定加引號 並且不帶on
  // (2) 同一個元素 同一個事件能夠添加多個偵聽器(事件處理程序)
   btns[1].addEventListener('click', function() {
       alert(22);
  })
   btns[1].addEventListener('click', function() {
           alert(33);
  })
   // 3. attachEvent ie9之前的版本支持
   btns[2].attachEvent('onclick', function() {
       alert(11);
  })
</script>

事件監聽兼容性解決方案

封裝一個函數,函數中判斷瀏覽器的類型:

 

 

3. 刪除事件(解綁事件)

 

 

    <div>1</div>
   <div>2</div>
   <div>3</div>
   <script>
       var divs = document.querySelectorAll('div');
       divs[0].onclick = function() {
           alert(11);
           // 1. 傳統方式刪除事件
           divs[0].onclick = null;
      }
       // 2. removeEventListener 刪除事件
       divs[1].addEventListener('click', fn) // 裏面的fn 不須要加小括號調用
       function fn() {
           alert(22);
           divs[1].removeEventListener('click', fn);
      }
       // 3. detachEvent
       divs[2].attachEvent('onclick', fn1);

       function fn1() {
           alert(33);
           divs[2].detachEvent('onclick', fn1);
      }
   </script>

刪除事件兼容性解決方案

 

 

4. DOM事件流

html中的標籤都是相互嵌套的,咱們能夠將元素想象成一個盒子裝一個盒子,document是最外面的大盒子。
當你單擊一個div時,同時你也單擊了div的父元素,甚至整個頁面。

那麼是先執行父元素的單擊事件,仍是先執行div的單擊事件 ???

事件流描述的是從頁面中接收事件的順序。

事件發生時會在元素節點之間按照特定的順序傳播,這個傳播過程DOM事件流

好比:咱們給頁面中的一個div註冊了單擊事件,當你單擊了div時,也就單擊了body,單擊了html,單擊了document。

 

 

  • 事件冒泡:IE最先提出,事件開始時由最具體的元素接收,而後逐級向上傳播到到DOM最頂層節點的過程。

  • 事件捕獲:網景最先提出,由DOM最頂層節點開始,而後逐級向下傳播到到最具體的元素接收的過程。

當時的2大瀏覽器霸主誰也不服誰!
IE 提出從目標元素開始,而後一層一層向外接收事件並響應,也就是冒泡型事件流。
Netscape(網景公司)提出從最外層開始,而後一層一層向內接收事件並響應,也就是捕獲型事件流。

江湖紛爭,武林盟主也腦袋疼!!!

最終,w3c 採用折中的方式,平息了戰火,制定了統一的標準 —--— 先捕獲再冒泡。
現代瀏覽器都遵循了此標準,因此當事件發生時,會經歷3個階段。

DOM 事件流會經歷3個階段:

  1. 捕獲階段

  2. 當前目標階段

  3. 冒泡階段

 

咱們向水裏面扔一塊石頭,首先它會有一個降低的過程,這個過程就能夠理解爲從最頂層向事件發生的最具體元素(目標點)的捕獲過程;以後會產生泡泡,會在最低點( 最具體元素)以後漂浮到水面上,這個過程至關於事件冒泡。

 

 

 

 

事件冒泡

    <div class="father">
       <div class="son">son盒子</div>
   </div>
   <script>
       // onclick 和 attachEvent(ie) 只在冒泡階段觸發
       // 冒泡階段 若是addEventListener 第三個參數是 false 或者 省略
       // son -> father ->body -> html -> document
       var son = document.querySelector('.son');
// 給son註冊單擊事件
       son.addEventListener('click', function() {
           alert('son');
      }, false);
// 給father註冊單擊事件
       var father = document.querySelector('.father');
       father.addEventListener('click', function() {
           alert('father');
      }, false);
// 給document註冊單擊事件,省略第3個參數
       document.addEventListener('click', function() {
           alert('document');
      })
   </script>

事件捕獲

    <div class="father">
       <div class="son">son盒子</div>
   </div>
   <script>
       // 若是addEventListener() 第三個參數是 true 那麼在捕獲階段觸發
       // document -> html -> body -> father -> son
        var son = document.querySelector('.son');
// 給son註冊單擊事件,第3個參數爲true
        son.addEventListener('click', function() {
            alert('son');
        }, true);
        var father = document.querySelector('.father');
// 給father註冊單擊事件,第3個參數爲true
        father.addEventListener('click', function() {
            alert('father');
        }, true);
// 給document註冊單擊事件,第3個參數爲true
       document.addEventListener('click', function() {
           alert('document');
      }, true)
   </script>

5. 事件對象

什麼是事件對象

官方解釋: event對象表明事件的狀態,好比鍵盤按鍵的狀態鼠標的位置、鼠標按鈕的狀態。

簡單理解:事件發生後,跟事件相關的一系列信息數據的集合都放到這個對象裏面,這個對象就是事件對象。

好比:

  1. 誰綁定了這個事件。

  2. 鼠標觸發事件的話,會獲得鼠標的相關信息,如鼠標位置。

  3. 鍵盤觸發事件的話,會獲得鍵盤的相關信息,如按了哪一個鍵。

事件對象的使用

事件觸發發生時就會產生事件對象,而且系統會以實參的形式傳給事件處理函數。

因此,在事件處理函數中聲明1個形參用來接收事件對象。

 

 

這個event是個形參,系統幫咱們設定爲事件對象,不須要傳遞實參過去。 當咱們註冊事件時,event 對象就會被系統自動建立,並依次傳遞給事件監聽器(事件處理函數) .

事件對象的兼容性處理

事件對象自己的獲取存在兼容問題:

  1. 標準瀏覽器中是瀏覽器給方法傳遞的參數,只須要定義形參 e 就能夠獲取到。

  2. 在 IE6~8 中,瀏覽器不會給方法傳遞參數,若是須要的話,須要到 window.event 中獲取查找。

 

 

只要「||」前面爲false, 無論「||」後面是true 仍是 false,都返回 「||」 後面的值。
只要「||」前面爲true, 無論「||」後面是true 仍是 false,都返回 「||」 前面的值。
    <div>123</div>
   <script>
       var div = document.querySelector('div');
       div.onclick = function(e) {
               // 事件對象
               e = e || window.event;
               console.log(e);
      }
   </script>

事件對象的屬性和方法

 

 

e.target 和 this 的區別

  • this 是事件綁定的元素(綁定這個事件處理函數的元素) 。

  • e.target 是事件觸發的元素。

常狀況下terget 和 this是一致的,
但有一種狀況不一樣,那就是在事件冒泡時(父子元素有相同事件,單擊子元素,父元素的事件處理函數也會被觸發執行),
這時候this指向的是父元素,由於它是綁定事件的元素對象,
而target指向的是子元素,由於他是觸發事件的那個具體元素對象。
    <div>123</div>
   <script>
       // 常見事件對象的屬性和方法
       // 1. e.target 返回的是觸發事件的對象(元素) this 返回的是綁定事件的對象(元素)
       // 區別 : e.target 點擊了那個元素,就返回那個元素 this 那個元素綁定了這個點擊事件,那麼就返回誰
       var div = document.querySelector('div');
       div.addEventListener('click', function(e) {
           // e.target 和 this指向的都是div
           console.log(e.target);
           console.log(this);

      });
   </script>

事件冒泡下的e.target和this

    <ul>
       <li>abc</li>
       <li>abc</li>
       <li>abc</li>
   </ul>
   <script>
       var ul = document.querySelector('ul');
       ul.addEventListener('click', function(e) {
               // 咱們給ul 綁定了事件 那麼this 就指向ul  
               console.log(this);
               console.log(e.currentTarget);

               // e.target 指向咱們點擊的那個對象 誰觸發了這個事件 咱們點擊的是li e.target 指向的就是li
               console.log(e.target);

          })
           // 瞭解兼容性
           // div.onclick = function(e) {
           //     e = e || window.event;
           //     var target = e.target || e.srcElement;
           //     console.log(target);

       // }
       // 2. 瞭解 跟 this 有個很是類似的屬性 currentTarget ie678不認識
   </script>

六、 阻止默認行爲

html中一些標籤有默認行爲,例如a標籤被單擊後,默認會進行頁面跳轉。

    <a href="http://www.baidu.com">百度</a>
   <script>
        // 常見事件對象的屬性和方法
       // 1. 返回事件類型
       var div = document.querySelector('div');
       div.addEventListener('click', fn);
       div.addEventListener('mouseover', fn);
       div.addEventListener('mouseout', fn);

       function fn(e) {
           console.log(e.type);

      }
       // 2. 阻止默認行爲 讓連接不跳轉
       var a = document.querySelector('a');
       a.addEventListener('click', function(e) {
            e.preventDefault(); // dom 標準寫法
      });
       // 3. 傳統的註冊方式
       a.onclick = function(e) {
           // 普通瀏覽器 e.preventDefault(); 方法
           e.preventDefault();
           // 低版本瀏覽器 ie678 returnValue 屬性
           e.returnValue = false;
           // 咱們能夠利用return false 也能阻止默認行爲 沒有兼容性問題
           return false;
      }
   </script>

7 、阻止事件冒泡

事件冒泡:開始時由最具體的元素接收,而後逐級向上傳播到到DOM最頂層節點。

事件冒泡自己的特性,會帶來的壞處,也會帶來的好處。

 

 

    <div class="father">
       <div class="son">son兒子</div>
   </div>
   <script>
       var son = document.querySelector('.son');
// 給son註冊單擊事件
       son.addEventListener('click', function(e) {
           alert('son');
           e.stopPropagation(); // stop 中止 Propagation 傳播
           window.event.cancelBubble = true; // 非標準 cancel 取消 bubble 泡泡 兼容性作法
      }, false);

       var father = document.querySelector('.father');
// 給father註冊單擊事件
       father.addEventListener('click', function() {
           alert('father');
      }, false);
// 給document註冊單擊事件
       document.addEventListener('click', function() {
           alert('document');
      })
   </script>

阻止事件冒泡的兼容性處理

 

 

八、 事件委託

事件冒泡自己的特性,會帶來的壞處,也會帶來的好處。

什麼是事件委託

把事情委託給別人,代爲處理。

事件委託也稱爲事件代理,在 jQuery 裏面稱爲事件委派。

說白了就是,不給子元素註冊事件,給父元素註冊事件,把處理代碼在父元素的事件中執行。

 

生活中的代理:

 

 

js事件中的代理:

事件委託的原理

不是每一個子節點單獨設置事件監聽器,而是事件監聽器設置在其父節點上,而後利用冒泡原理影響設置每一個子節點。(給父元素註冊事件,利用事件冒泡,當子元素的事件觸發,會冒泡到父元素,而後去控制相應的子元素。)

以上案例:給ul註冊點擊事件,而後利用事件對象的target來找到當前點擊的li ,由於點擊li,事件會冒泡到ul上,

ul有註冊事件,就會觸發事件監聽器。

事件委託的做用

  • 咱們只操做了一次 DOM ,提升了程序的性能。

  • 動態新建立的子元素,也擁有事件。

    <ul>
       <li>知否知否,點我應有彈框在手!</li>
       <li>知否知否,點我應有彈框在手!</li>
       <li>知否知否,點我應有彈框在手!</li>
       <li>知否知否,點我應有彈框在手!</li>
       <li>知否知否,點我應有彈框在手!</li>
   </ul>
   <script>
       // 事件委託的核心原理:給父節點添加偵聽器, 利用事件冒泡影響每個子節點
       var ul = document.querySelector('ul');
       ul.addEventListener('click', function(e) {
           // e.target 這個能夠獲得咱們點擊的對象
           e.target.style.backgroundColor = 'pink';
      })
   </script>
相關文章
相關標籤/搜索