JavaScript事件是指什麼

藏色散人
發布: 2022-01-19 15:39:00
原創
3333 人瀏覽過

JavaScript事件是指在文件或瀏覽器中發生的一些特定互動瞬間,例如開啟某一個網頁,瀏覽器載入完成後會觸發load事件,當滑鼠懸浮於某一個元素上時會觸發hover事件,當滑鼠點擊某一個元素時會觸發click事件等等。

JavaScript事件是指什麼

本文操作環境:Windows7系統、javascript1.8.5版、DELL G3電腦

JavaScript事件是指什麼?

JavaScript 事件詳解

JavaScript 事件解讀

1. 事件基本概念

事件是指在文件或瀏覽器中發生的一些特定互動瞬間,例如開啟某一個網頁,瀏覽器載入完成後會觸發load 事件,當滑鼠懸浮於某一個元素上時會觸發hover 事件,當滑鼠點擊某一個元素時會觸發click 事件等等。

事件處理就是當事件被觸發後,瀏覽器回應這個事件的行為,而這個行為所對應的程式碼即為事件處理程序

2. 事件操作:監聽與移除監聽

2.1 監聽事件

瀏覽器會根據一些事件作出相對應的事件處理,事件處理的前提是需要監聽事件,監聽事件的方法主要有以下三種:

2.1.1 HTML 內嵌屬性

即在HTML 元素裡直接填入與事件相關的屬性,屬性值為事件處理程式.範例如下:

<button></button>
登入後複製

onclick 對應著click 事件,所以當按鈕被點擊後,便會執行事件處理程序,即控制台輸出You clicked me!

不過我們需要指出的是,這種方式將 HTML 程式碼與 JavaScript 程式碼耦合在一起,不利於程式碼的維護,所以應該盡量避免使用這樣的方式。

2.1.2 DOM 屬性綁定

透過直接設定某個DOM 節點的屬性來指定事件和事件處理程序,上碼:

const btn = document.getElementById("btn");
btn.onclick = function(e) {
    console.log("You clicked me!");
};
登入後複製

上面範例中,首先取得btn 這個對象,透過為這個物件加上onclick 屬性的方式來監聽click 事件,這個屬性值對應的就是事件處理程序。這段程式也被稱為 DOM 0 級事件處理程序。

2.1.3 事件監聽函數

標準的事件監聽函數如下:

const btn = document.getElementById("btn");
btn.addEventListener("click", () => {
    console.log("You clicked me!");
}, false);
登入後複製

上面的範例表示先獲得表示節點的btn 對象,然後在這個物件上面添加了一個事件監聽器,當監聽到click 事件發生時,則呼叫回呼函數,即在控制台輸出You clicked me!addEventListener 函數包含了三個參數 false,第三個參數的意義在後面的事件觸發三個階段之後再講解。這段程序也被稱為 DOM 2 級事件處理程序。 IE9 、FireFox、Safari、Chrome 和 Opera 都是支援 DOM 2 級事件處理程序的,對於 IE8 及以下版本,則用 attacEvent() 函數綁定事件。

所以我們可以寫一段具有相容性的程式碼:

function addEventHandler(obj, eventName, handler) {
    if (document.addEventListener) {
        obj.addEventListener(eventName, handler, false);
    }
    else if (document.attachEvent) {
        obj.attachEvent("on" + eventName, handler);
    }    
    else {
        obj["on" + eventName] = handler;
    }
}
登入後複製

2.2 移除事件監聽

在為某個元素綁定了一個事件後,如果想接觸綁定,則需要用到removeEventListener 方法。看如下例子:

const handler = function() {
    // handler logic
}
const btn = document.getElementById("btn");

btn.addEventListener("click", handler);
btn.removeEventListener("click", handler);
登入後複製

要注意的是,綁定事件的回呼函數不能是匿名函數,必須是已經被宣告的函數,因為解除事件綁定時需要傳遞這個回呼函數的參考。

同樣,IE8 及以下版本也不支援上面的方法,而是用 detachEvent 取代。

const handler = function() {
    // handler logic
}
const btn = document.getElementById("btn");

btn.attachEvent("onclick", handler);
btn.detachEvent("onclick", handler);
登入後複製

同樣,可以寫一段具有相容性的刪除事件函數:

function removeEventHandler(obj, eventName, handler) {
    if (document.removeEventListener) {
        obj.removeEventListener(eventName, handler, false);
    }
    else if (document.detachEvent) {
        obj,detachEvent("on" + eventName, handler);
    }
    else {
        obj["on" + eventName] = null;
    }
}
登入後複製

3. 事件觸發過程

事件流描述了頁面接收事件的順序。現代瀏覽器(指IE6-IE8 除外的瀏覽器,包括IE9 、FireFox、Safari、Chrome 和Opera 等)事件流包含三個過程,分別是捕獲階段、目標階段和冒泡階段,下圖形像地說明這個過程:

JavaScript事件是指什麼

下面就詳細地講解這三個過程。

3.1 捕獲階段

當我們對DOM 元素進行操作時,例如滑鼠點擊、懸浮等,就會有一個事件傳輸到這個DOM 元素,這個事件從Window 開始,依序經過docuemnt、html、body,再不斷經過子節點直到到達目標元素,從Window 到達目標元素父節點的過程稱為捕獲階段,注意此時還未到達目標節點。

3.2 目標階段

捕獲階段結束時,事件到達了目標節點的父節點,最終到達目標節點,並在目標節點上觸發了這個事件,這就是目標階段

要注意的是,事件觸發的目標節點為最底層的節點。例如下面的例子:

<div>
    <p>你猜,目标在这里还是<span>那里</span>。</p>
</div>
登入後複製

当我们点击“那里”的时候,目标节点是<span></span>,点击“这里”的时候,目标节点是<p></p>,而当我们点击<p></p>区域之外,<p></p>区域之内时,目标节点就是<p></p>

3.3 冒泡阶段

当事件到达目标节点之后,就会沿着原路返回,这个过程有点类似水泡从水底浮出水面的过程,所以称这个过程为冒泡阶段

针对这个过程,wilsonpage 做了一个 DEMO,可以非常直观地查看这个过程。

现在再看 addEventListener(eventName, handler, useCapture) 函数。第三个参数是 useCapture,代表是否在捕获阶段进行事件处理, 如果是 false, 则在冒泡阶段进行事件处理,如果是 true,在捕获阶段进行事件处理,默认是 false。这么设计的主要原因是当年微软和 netscape 之间的浏览器战争打得火热,netscape 主张捕获方式,微软主张冒泡方式,W3C 采用了折中的方式,即先捕获再冒泡。

4、事件委托

上面我们讲了事件的冒泡机制,我们可以利用这一特性来提高页面性能,事件委托便事件冒泡是最典型的应用之一。

何谓“委托”?在现实中,当我们不想做某件事时,便“委托”给他人,让他人代为完成。JavaScript 中,事件的委托表示给元素的父级或者祖级,甚至页面,由他们来绑定事件,然后利用事件冒泡的基本原理,通过事件目标对象进行检测,然后执行相关操作。看下面例子:

// HTML
<ul id="list">
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
    <li>Item 5</li>
</ul>

// JavaScript
var list = document.getElementById("list");
list.addEventListener("click", function(e) {
    console.log(e.target);
});
登入後複製

上面的例子中,5 个列表项的点击事件均委托给了父元素 <ul id="list"></ul>

先看看事件委托的可行性。有人会问,当事件不是加在某个元素上的,如何在这个元素上触发事件呢?我们就是利用事件冒泡的机制,事件流到达目标元素后会向上冒泡,此时父元素接收到事件流便会执行事件执行程序。有人又会问,被委托的父元素下面如果有很多子元素,怎么知道事件流来自于哪个子元素呢?这个我们可以从事件对象中的 target 属性获得。事件对象下面会详细讲解。

我们再来看看为什么需要事件委托。

  • 减少事件绑定。上面的例子中,也可以分别给每个列表项绑定事件,但利用事件委托的方式不仅省去了一一绑定的麻烦,也提升了网页的性能,因为每绑定一个事件便会增加内存使用。

  • 可以动态监听绑定。上面的例子中,我们对 5 个列表项进行了事件监听,当删除一个列表项时不需要单独删除这个列表项所绑定的事件,而增加一个列表项时也不需要单独为新增项绑定事件。

看了上面的例子和解释,我们可以看出事件委托的核心就是监听一个 DOM 中更高层、更不具体的元素,等到事件冒泡到这个不具体元素时,通过 event 对象的 target 属性来获取触发事件的具体元素。

5、阻止事件冒泡

事件委托是事件冒泡的一个应用,但有时候我们并不希望事件冒泡。比如下面的例子:

const ele = document.getElementById("ele");
ele.addEventListener("click", function() {
    console.log("ele-click");
}, false);

document.addEventListener("click", function() {
    console.log("document-click");
}, false);
登入後複製

我们本意是当点击 ele 元素区域时显示 "ele-click",点击其他区域时显示 "document-click"。但是我们发现点击 ele 元素区域时会依次显示 "ele-click" "document-click"。那是因为绑定在 ele 上的事件冒泡到了 document 上。想要解决这个问题,只需要加一行代码:

const ele = document.getElementById("ele");
ele.addEventListener("click", function(e) {
    console.log("ele-click");
    e.stopPropagation(); // 阻止事件冒泡
}, false);

document.addEventListener("click", function(e) {
    console.log("document-click");
}, false);
登入後複製

我们还能用 e.cancelBubble = true 来替代 e.stopPropagation()。网上的说法是 cancelBubble 仅仅适用于 IE,而 stopPropagation 适用于其他浏览器。但根据我实验的结果,现代浏览器(IE9 及 以上、Chrome、FF 等)均同时支持这两种写法。为了保险起见,我们可以采用以下代码:

function preventBubble(e) {
    if (!e) {
        const e = window.event;
    }
    e.cancelBubble = true;
    if (e.stopPropagation) {
        e.stopPropagation();
    }
}
登入後複製

6、event 对象

Event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。当一个事件被触发的时候,就会创建一个事件对象。

我们用下面的代码打印出事件对象:

<div id="list">
    <li>Item 1</li>
    <li>Item 2</li>
</div>
<script>
    var list = document.getElementById("list");
    list.addEventListener("click", function(e) {
        console.log(e);
    });
</script>
登入後複製

chrome 49 的运行结果如下:

JavaScript事件是指什麼

下面介绍一些比较常用的属性和方法。

target、 srcElement、 currentTarget 和 relatedTarget、fromElement、 toElement

  • target 与 srcElement 完全相同;

  • target 指觸發事件的元素,currentTarget 指事件所綁定的元素;

  • relatedTarget:與事件的目標節點相關的節點。對於 mouseover 事件來說,該屬性是滑鼠指標移到目標節點上時所離開的那個節點。對於 mouseout 事件來說,該屬性是離開目標時,滑鼠指標進入的節點。
    對於其他類型的事件來說,這個屬性沒有用;

  • fromElement 和 toElement 僅對於 mouseover 和 mouseout 事件有效。

以上面的範例說明,當點選<li>Item 1</li> 時,target 就是<li>Item 1</li> 元素,而currentTarget 是<p id="list"></p>

clientX/Y、 screenX/Y、 pageX/Y、 offsetX/Y

上圖:

  • offsetX/Y: 點選位置相對於所處元素左上角的位置;

  • #clientX/Y: 點選位置相對於瀏覽器內容區域左上角的位置;

  • screenX/Y: 點選位置相對於螢幕左上角的位置;

  • ##pageX/Y: 點選位置相對整個頁面左上角的位置;<p></p>
  • pageX/Y 與clientX/Y 一般情況下會相同,只有出現捲軸時才不一樣。 <p></p>
altKey、 ctrlKey、 shiftKey

  • #altKey: 傳回當事件觸發時,"ALT" 是否被按下;<p></p>
  • ctrlKey: 傳回當事件觸發時,"CTRL" 鍵是否被按下;<p></p>
  • shiftKey: 傳回當事件觸發時,"SHIFT"鍵是否被按下;<p></p>
其他屬性

  • #type: 傳回目前Event 物件表示的事件的名稱<p></p>
  • bubbles: 傳回布林值,指示事件是否為起泡事件類型;<p></p>
  • #cancelable: 傳回布林值,指示事件是否可支援可取消的預設動作;<p></p>
  • eventPhase: 傳回事件傳播的目前階段,有三個值: Event.CAPTURING_PHASE、 Event.AT_TARGET、 Event.BUBBLING_PHASE,對應的值為1、2、3,分別表示捕獲階段、正常事件派發和起泡階段;<p></p>
  • path:冒泡階段經過的節點;<p></p>

  • <p></p>#preventDefault(): 通知瀏覽器不要執行與事件關聯的預設動作;
  • <p></p>stopPropagation(): 阻止冒泡;

########################## ###推薦學習:《######js基礎教學######》######

以上是JavaScript事件是指什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板