js中事件物件event

冰雪為融發表於2018-03-06

一、Event物件

Event 物件代表事件的狀態,比如事件在其中發生的元素、鍵盤按鍵的狀態、滑鼠的位置、滑鼠按鈕的狀態。

事件通常與函式結合使用,函式不會在事件發生前被執行!

當一個事件發生的時候,和當前這個物件發生的這個事件有關的一些詳細資訊(包括導致事件的元素、事件的型別、以及其它與特定事件相關的資訊等。這個物件是在執行事件時,瀏覽器通過函式傳遞過來的。)都會被臨時儲存到一個指定的地方——event物件,供我們在需要的時候呼叫

二、獲取event物件

在 W3C 規範中,event 物件是隨事件處理函式傳入的,Chrome、FireFox、Opera、Safari、IE9.0及其以上版本都支援這種方式;但是對於 IE8.0 及其以下版本,event 物件必須作為 window 物件的一個屬性。

 

IE、Chrome:event是一個內建的全域性物件

標準下/FF:事件物件是通過事件函式的第一個引數傳入(如果一個函式是被事件呼叫的,那麼這個函式定義的第一個引數就是事件物件)

如何處理相容性:

document.onclick = function  fn(){
   var ev = ev||event;
   alert('處理相容');
}

例子:

<script>

    window.onload = function(){
        var oDiv = document.getElementById('div1');
        document.onmousemove = function(ev){
            var ev = ev||event;//處理相容性
            oDiv.style.left = ev.clientX + 'px';
            oDiv.style.top = ev.clientY + 'px';
        }
    }

</script>

三、事件流

事件流是描述的從頁面接受事件的順序,當幾個都具有事件的元素層疊在一起的時候而層疊在你點選範圍 , 並不是只有當前被點選的元素會觸發事件 , 那麼你點選其中一個元素的所有元素都會觸發事件。而如果我們想要只觸發其中一個事件時,此時就需要取消冒泡或捕獲。現代瀏覽器預設都是冒泡型別,所以通常只需要取消冒泡即可。 

事件流包括兩種模式:冒泡和捕獲

   1、冒泡:從裡向外逐個觸發。當你使用事件冒泡時,子級元素先觸發,父級元素後觸發

 事件冒泡機制:當一個元素接收到事件的時候,會把他接收的所有傳播給他的父級,一直到頂層window

   2、捕獲:從外向裡逐個觸發(與事件冒泡機制相反)當你使用事件捕獲時,父級元素先觸發,子級元素後觸發

W3C模型

W3C模型是將兩者進行中和,在W3C模型中,任何事件發生時,先從頂層開始進行事件捕獲,直到事件觸發到達了事件源元素。然後,再從事件源往上進行事件冒泡,直到到達document。

阻止事件冒泡的方法

function stopBubble(e) {  
  if(e && e.stopPropagation){  
      e.stopPropagation();  //非IE下
  } else {  
    window.event.cancelBubble = true;  //IE下
  }  
};  

四、js事件繫結

要想讓 JavaScript 對使用者的操作作出響應,首先要對 DOM 元素繫結事件處理函式。所謂事件處理函式,就是處理使用者操作的函式,不同的操作對應不同的名稱。
在JavaScript中,有三種常用的繫結事件的方法:

  1. 在DOM元素中直接繫結;
  2. 在JavaScript程式碼中繫結;
  3. 繫結事件監聽函式。

1、在DOM中直接繫結

<button onclick="open()">按鈕</button>

<script>
function open(){
    alert(1);
}
</script>

2、在js程式碼中繫結

<button id="btn">按鈕</button>

document.getElementById('btn').onclick = function(){
      this.style.background = 'yellow';
  }

3、繫結事件監聽函式

繫結事件的另一種方法是用 addEventListener() 或 attachEvent() 來繫結事件監聽函式。

addEventListener()函式語法:
elementObject.addEventListener(eventName,handle,useCapture);

引數 說明
elementObject DOM物件(即DOM元素)。
eventName 事件名稱。注意,這裡的事件名稱沒有“ on ”,如滑鼠單擊事件 click ,滑鼠雙擊事件 doubleclick ,滑鼠移入事件 mouseover,滑鼠移出事件 mouseout 等。
handle 事件控制程式碼函式,即用來處理事件的函式。
useCapture Boolean型別,是否使用捕獲,一般用false 。這裡涉及到JavaScript事件流的概念,前面已經進行了講解


attachEvent()函式語法:
elementObject.attachEvent(eventName,handle);

引數 說明
elementObject DOM物件(即DOM元素)。
eventName 事件名稱。注意,與addEventListener()不同,這裡的事件名稱有“ on ”,如滑鼠單擊事件 onclick ,滑鼠雙擊事件 ondoubleclick ,滑鼠移入事件 onmouseover,滑鼠移出事件 onmouseout 等。
handle 事件控制程式碼函式,即用來處理事件的函式。


注意:事件控制程式碼函式是指“ 函式名 ”,不能帶小括號。
addEventListener()是標準的繫結事件監聽函式的方法,是W3C所支援的,Chrome、FireFox、Opera、Safari、IE9.0及其以上版本都支援該函式;但是,IE8.0及其以下版本不支援該方法,它使用attachEvent()來繫結事件監聽函式。所以,這種繫結事件的方法必須要處理瀏覽器相容問題。     

下面繫結事件的程式碼,進行了相容性處理,能夠被所有瀏覽器支援:

<button id="btn">按鈕</button>

<script type="text/javascript">
        var oBtn = document.getElementById('btn');
        function addEvent(obj,type,handle){
            try{ // Chrome、FireFox、Opera、Safari、IE9.0及其以上版本
                obj.addEventListener(type,handle,false);
            }catch(e){
                try{ // IE8.0及其以下版本
                    obj.attachEvent('on' + type,handle);
                }catch(e){ // 早期瀏覽器
                    obj['on' + type] = handle;
                }
            }
        }
        addEvent(oBtn,'click',function(){//切記cliclk要加引號,沒加會報錯
            this.style.width = 200+'px';
        });
</script>
<span style="color:#ffcc33">這裡使用 try{ ... } catch(e){ ... } 代替 if ... else... 語句,避免瀏覽器出現錯誤提示。</span>

注意:obj.addEventListener('click',fn,true);(從外到裡)//告訴Obj,如果有一個進去的事件觸發了你,你就去執行fn這個函式              obj.addEventListeren('click',fn,false);(從裡到外)//告訴Obj,如果有一個出去的事件觸發了你,你就去執行fn這個函式

總結一下就是:如果最後一個布林值引數是true,就表示,在捕獲階段呼叫事件處理程式,如果是false,就表示在冒泡階段呼叫事件處理程式

4、三種繫結事件的區別

第一種方式:函式寫在結構層裡面。非常不好,使頁面很混亂,行為與結構得不到分離。並且在DOM結構如果繫結兩個 "onclick" 事件,只會執行第一個;

第二種方式:行為與結構開始分離。第二種繫結方式中只能給一個時間繫結一個處理函式,在指令碼通過匿名函式的方式繫結的只會執行最後一個事件。

第三種方式:可以繫結多次同一個事件,且都會執行

1. <div id="btn" onclick="clickone()" onclick="clicktwo()"></div> 

    <script>

     function clickone(){ alert("hello"); } //執行這個

     function clicktwo(){ alert("world!"); }

    </script>

  2. <div id="btn"></div>

    <script>

     document.getElementById("btn").onclick = function(){ alert("hello"); }

     document.getElementById("btn").onclick = function(){ alert("world"); } //執行這個

    </script>

  3. <div id="btn"></div>

    <script>

     document.getElementById("btn").addeventlistener("click",clickone,false);

     function clickone(){ alert("hello"); } //先執行

     document.getElementById("btn").addeventlistener("click",clicktwo,false);

     function clicktwo(){ alert("world"); } //後執行

    </script>

5、如何取消事件繫結

第一種方式:document.onclick = null;(針對第一和第二兩種繫結方式)

第二種方式:obj.detachEvent(事件名稱,事件函式);(針對非標準IE下的繫結方式)

第三種方式:obj.removeEventListener(事件名稱,事件函式,是否捕獲);(針對標準瀏覽器下的繫結方式)

五、js事件委託

事件委託:利用事件冒泡的特性,將裡層的事件委託給外層事件,根據event物件的屬性進行事件委託,改善效能。

使用事件委託能夠避免對特定的每個節點新增事件監聽器;事件監聽器是被新增到它們的父元素上。事件監聽器會分析從子元素冒泡上來的事件,找到是哪個子元素的事件。(事件委託看起來挺難理解,但是舉個生活的例子。比如,有三個同事預計會在週一收到快遞。為簽收快遞,有兩種辦法:一是三個人在公司門口等快遞;二是委託給前臺MM代為簽收。)

 

 

<ul id="ul-item">
    <li class="item">item1</li>
    <li class="item">item2</li>
    <li class="item">item3</li>
    <li class="item">item4</li>
</ul>

<script type="text/javascript">
    function fn(){
        var oUlItem = document.getElementById('ul-item');
        oUlItem.addEventListener('click',show,false);//新增監聽事件
        function show(ev){
            var  ev = ev || window.event;
            var src = ev.target||ev.srcElement;//相容IE下和FF下以及其他瀏覽器
            if(src && src.className.toLowerCase() === 'item'){//tolowerCase,將字串全部轉化為小寫字母
                alert(src.innerHTML);
            }
        }
    };
    fn();
</script>

以下為補充知識(js的event.srcElement與event.target(觸發事件源))

IE下,event物件有srcElement屬性,但是沒有target屬性;

Firefox下,event物件有target屬性,但是沒有srcElement屬性.但他們的作用是相當的,即:

firefox 下的 event.target = IE 下的 event.srcElement

解決方法:使用obj = event.srcElement ? event.srcElement : event.target;

或:var evtTarget = event.target || event.srcElement;

js將html的所有控制元件都看成是一個個物件,通過js的各個屬性,就能對其進行操作處理,js裡物件的整體結構是樹形的結構。一層一層的追溯,即可獲取需要的結果。

event.srcElement:表示的當前的這個事件源。

event.srcElement.parentNode:表示當前事件源的父節點。

 parentNode:父節點,也就是上一層的節點。可以是任何一個標籤。

event.srcElement.firstChild:當前事件的第一個節點,如果節點是input,通過event.srcElement.firstChild.value就可以獲取此input的值。

event.srcElement.parentElement:是指在滑鼠所在物件的上一個物件。

event.srcElement.children:當前節點下物件的個數,有多個的話就是個陣列,如當前節點下有2個input的物件,要獲取這兩個可以用event.srcElement.children[0] 與 event.srcElement.children[1]分別獲取。

 

 

 

相關文章