JavaScript學習總結(九)事件詳解

其實這篇文章挺早以前就寫了,可是因爲sf保存方面的bug,因此當時寫了一大堆,結果沒保存,以爲這個沒寫完是個不小的遺憾,今天正好有空,就給補充下了,也正好給個人javascript學習總結作一個完結篇。javascript

其實以前的文章也涉及到部分事件,能夠參照個人文章:JavaScript學習總結(三)BOM和DOM詳解html

這裏,主要討論一下js相關的事件——java

事件處理程序

DOM中定義了一些事件, 而響應某個事件的函數就叫事件處理程序(或事件偵聽器)。事件處理程序的名字通常以「on」開頭,例如:onclicknode

事件冒泡與捕獲

事件流指的是頁面中接收事件的順序,IE,火狐和chrome瀏覽器都是事件冒泡,所謂是事件冒泡指的是事件最開始由最具體的元素接收,而後逐級向上傳播到不具體的節點。而事件捕獲則正好相反,事件捕獲是由Netscape提出的,事件冒泡和捕獲具體以下圖所示:jquery

2012062314423159.png

雖然事件捕獲是Netscape惟一支持的事件流模型,但目前IE9,火狐和谷歌也都支持這種事件流模型。正則表達式

事件冒泡的好處

由於事件具備冒泡機制,所以咱們能夠利用冒泡的原理,把事件加到父級上,觸發執行效果。這樣作的好處固然就是提升性能了,chrome

<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <script type="text/javascript">
        window.onload = function () {
            var aUl = document.getElementsById("bubble");
            var aLi = aUl.getElementsByTagName("li");

            for(var i = 0;i<aLi.length;i++){
                aLi[i].onmouseover = function () {
                    this.style.backgroundColor = "blue";
                };
                ali[i].onmouseout = function () {
                    this.style.backgroundColor = "";
                }
            }
        };
    </script>
</head>
<body>
<div>
    <ul id = "bubble">
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
    </ul>
</div>
</body>

這樣咱們就能夠作到li上面添加鼠標事件。可是若是說咱們可能有不少個lifor循環的話就比較影響性能。
下面咱們能夠用事件委託的方式來實現這樣的效果。html不變:segmentfault

<script type="text/javascript">
    window.onload = function () {
        var aUl = document.getElementsById("bubble");
        var aLi = aUl.getElementsByTagName("li");
        
        //無論在哪一個事件中,只要你操做的那個元素就是事件源。
        // ie:window.event.srcElement
        // 標準下:event.target
        aUl.onmouseover = function (ev) {
            var ev = ev || window.event;
            var target = ev.target || ev.srcElement;

            if(target.nodeName.toLowerCase() == "li"){
                target.style.background = "blue";
            }
        };
        aUl.onmouseout = function (ev) {
            var ev = ev || window.event;
            var target = ev.target || ev.srcElement;

            if(target.nodeName.toLowerCase() = "li"){
                target.style.background = "";
            }
        }
        };
</script>

那麼,如何阻止事件的冒泡呢,看下面一個例子:數組

<div onclick="showMsg(this,event)" id="outSide" style="width:100px; height:100px; background:#000; padding:50px">
<div onclick="showMsg(this,event)" id="inSide" style="width:100px; height:100px; background:#CCC"></div>
</div>
<script type="text/javascript">
//阻止事件冒泡後,你點擊灰色盒子,整個過程只彈一次對話框了(注意與默認狀況對比)
function showMsg(obj,e)
{
    alert(obj.id);
    stopBubble(e)
}

//阻止事件冒泡函數
function stopBubble(e)
{
    if (e && e.stopPropagation)
        e.stopPropagation()
    else
        window.event.cancelBubble=true
}
</script>

點擊黑色外圍的效果圖:瀏覽器

圖片描述

DOM 0級事件處理程序

經過js指定事件處理程序一般是將回調函數賦給這個事件處理程序的屬性。每一個元素都有本身的事件處理程序屬性(屬性小寫,例如:onclick

btn.onclick = function(){
    console.log('hello');
};

使用DOM 0級指定的事件處理程序被認爲是元素的方法。所以,this指向當前元素:

var btn = document.getElementById('myDiv');

//DOM上觸發的事件會產生一個事件對象event
btn.onclick = function (event) {
    alert(this.id);//myDiv  
};

DOM level 1

DOM level 1 專一於 HTMLXML 文檔模型。它含有文檔導航和處理功能。

DOM level 1 於 1998 年 10 月 1 日成爲 W3C 推薦標準。

第二版的工做草案在 2000 年 9 月 29 日。

值得一提的是:DOM level 0 並非 W3C 規範。而僅僅是對在 Netscape Navigator 3.0IE 3.0 中的等價功能性的一種定義。

DOM 2級事件處理程序

DOM 2級定義了兩個方法,用於指定和刪除事件處理程序的操做:addEventListener()removeEventListener(),他們都接受三個參數:

1.事件名。好比上面的click
2.做爲事件處理程序的函數。
3.布爾值(true表示捕獲階段調用事件處理程序,false表示冒泡階段)

經過Element對象的addEventListener方法,也能夠定義事件的回調函數。

//element.addEventListener(event, function, useCapture) 

var btn = document.getElementById('myDiv');
btn.addEventListener('click', function () {
    console.log(this.id);
},false);

IE中的事件處理程序

IE9以前的IE瀏覽器不支持addEventListener()removeEventListener()
與其餘瀏覽器不一樣的是,IE使用的是attachEvent()detachEvent()方法來爲DOM添加事件處理程序,因爲IE8及更早版本只支持事件冒泡,因此他們只接受兩個參數:

一、事件處理程序名稱(前面要加on)
二、事件處理程序函數

使用attachEvent()添加的事件處理程序以下:

var btn = document.getElementById('myDiv');
btn.attachEvent('onclick', function () {
    console.log(this.id);
});

值得注意的是,使用attachEvent()方法的狀況下,事件處理程序會在全局做用域中運行,因此,此時this等於window

事件對象

在觸發DOM上的某個事件時,會產生一個事件對象event,這個對象包含着全部與事件相關的信息。包括致使事件的元素、事件的類型以及其餘與特定事件相關的信息。event對象會被做爲第一個參數傳遞給事件監聽的回調函數。咱們能夠經過這個event對象來獲取到大量當前事件相關的信息:

type (String) — 事件的名稱
target (node) — 事件起源的DOM節點
currentTarget?(node) — 當前回調函數被觸發的DOM節點(後面會作比較詳細的介紹)
bubbles (boolean) — 指明這個事件是不是一個冒泡事件(接下來會作解釋)
preventDefault(function) — 這個方法將阻止瀏覽器中用戶代理對當前事件的相關默認行爲被觸發。好比阻止<a>元素的click事件加載一個新的頁面
cancelable (boolean) — 這個變量指明這個事件的默認行爲是否能夠經過調用event.preventDefault來阻止。
stopPropagation (function) — 取消事件的進一步捕獲或冒泡,bubbles爲true使用這個方法
eventPhase:返回一個數字,表示事件目前所處的階段,0爲事件開始從DOM表層向目標元素傳播,1爲捕獲階段,2爲事件到達目標元素,3爲冒泡階段。

此外,事件對象還可能擁有不少其餘的屬性,可是他們都是針對特定的event的。好比,鼠標事件包含clientXclientY屬性來代表鼠標在當前視窗的位置。

另外,stopPropagation()方法用於當即中止事件在DOM中的傳播,即取消進一步的事件冒泡或捕獲。

var btn = document.getElementById('myDiv');
btn.onclick = function (event) {
    alert("clicked");
    event.stopPropagation();
};

//避免觸發在document.body上的事件處理程序
document.body.onclick = function (event) {
    alert("Body clicked");  
};

只有在事件處理程序執行期間,event對象纔會存在,一旦事件處理程序執行完畢,event對象就會自動銷燬。

IE中的事件對象

DOM 0級中添加事件處理程序時,event對象是做爲window對象的一個屬性存在的:

var btn = document.getElementById('myDiv');
btn.onclick = function (event) {
    var event = window.event;
    alert(event.type);//click
};

IE 的event對象一樣也包含與建立它的事件相關的屬性和方法。

cancleBubble 布爾   默認值時false,但能夠被設置成true來取消事件冒泡,與dom中的 stopPropagation()方法相同。
returnValue  布爾    默認值是true,當設置成false時用以取消事件的默認行爲 與dom中的preventDefault()相同。
srcElement  元素    事件的目標,與dom中的target屬性相同。
type     字符串   被觸發的事件類型。

click事件

當用戶點擊之後,event對象會包含如下屬性。

pageX,pageY:點擊位置相對於html元素的座標,單位爲像素。
clientX,clientY:點擊位置相對於視口(viewport)的座標,單位爲像素。
screenX,screenY:點擊位置相對於設備顯示屏幕的座標,單位爲設備硬件的像素

clientX,clientY

圖示:clientXclientY,他們的值表示事件發生時鼠標指針在視口中的水平和垂直座標(不包含滾動條區域)
圖片描述

偏移量

經過如下4個屬性能夠取得元素的偏移量。

   (1)offsetHeight:元素在垂直方向上佔用的空間大小,以像素計。包括元素的高度、(可見的)水平滾動條的高度、上邊框高度和下邊框高度。

   (2)offsetWidth:元素在水平方向上佔用的空間大小,以像素計。包括元素的寬度、(可見的)垂直滾動條的寬度、左邊框寬度和右邊框寬度。

   (3)offsetLeft:元素的左外邊框至包含元素的左內邊框之間的像素距離。

   (4)offsetTop:元素的上外邊框至包含元素的上內邊框之間的像素距離。

pageX,pageY

這兩個屬性表示鼠標光標在頁面中的位置,在頁面沒有滾動的狀況下,pageXpageY的值與clientXclientY的值相等

滾動大小

滾動大小,指的是包含滾動內容的元素的大小。

如下是4個與滾動大小相關的屬性。

   (1)scrollHeight:在沒有滾動條的狀況下,元素內容的總高度。

   (2)scrollWidth:在沒有滾動條的狀況下,元素內容的總寬度。

   (3)scrollLeft:被隱藏在內容區域左側的像素數。經過設置這個屬性能夠改變元素的滾動位置。

   (4)scrollTop:被隱藏在內容區域上方的像素數。經過設置這個屬性能夠改變元素的滾動位置。

焦點事件

焦點事件會在頁面元素得到或失去焦點時觸發,有如下4個焦點事件:

1. blur:元素失去焦點時觸發,該事件不冒泡
 2. focus:元素得到焦點時觸發。不冒泡
 3. focusin:元素得到焦點時觸發,冒泡
 4. focusout:元素失去焦點時觸發,冒泡

鼠標事件

DOM 3級定義了9個鼠標事件:

click:當用戶點擊鼠標主鍵一般是指鼠標左鍵或按回車鍵時觸發。

dbclick:用戶雙擊鼠標時觸發

mousedown:當用戶按下鼠標任意一個鍵都會觸發,這個事件是不可以經過鍵盤觸發的。

mousemove:當鼠標在某元素周圍移動時重複觸發,該事件不能經過鍵盤事件觸發。

mouseout:當鼠標離開元素時觸發,這個事件不能經過鍵盤觸發。

mouseover:當鼠標進入元素時觸發,這個事件不可以經過鍵盤觸發。
 mouseenter:相似「mouseover」,但不冒泡,並且當光標移到後代元素上不會觸發。 

mouseleave:相似「mouseout」,但不冒泡。在元素上方是不觸發。

mouseup:當用戶釋放鼠標按鍵時觸發,不可以經過鍵盤觸發。


傳遞給鼠標事件處理程序的事件對象有clientX和clientY屬性,它們指定了鼠標指針相對於包含窗口的座標。加入窗口的滾動偏移量,就能夠把鼠標位置轉換成文檔座標。

  頁面上的全部元素都支持鼠標事件。除了mouseentermouseleave外,全部的事件都冒泡,而且他們的默認行爲是能夠被取消掉的。但取消鼠標事件的默認行爲可能會影響到其餘事件,由於有些鼠標事件是相互依賴的。

mouseentermouseover的不一樣:
http://www.w3school.com.cn/ti...

拖拉事件

(1)drag事件

drag事件在源對象被拖拉過程當中觸發。

(2)dragstartdragend事件

dragstart事件在用戶開始用鼠標拖拉某個對象時觸發,dragend事件在結束拖拉時觸發。

(3)dragenterdragleave事件

dragenter事件在源對象拖拉進目標對象後,在目標對象上觸發。dragleave事件在源對象離開目標對象後,在目標對象上觸發。

(4)dragover事件

dragover事件在源對象拖拉過另外一個對象上方時,在後者上觸發。

(5)drop事件

當源對象被拖拉到目標對象上方,用戶鬆開鼠標時,在目標對象上觸發drop事件。

相關文章

  1. JavaScript學習總結(一)基礎部分
  2. JavaScript學習總結(二)數組和對象部分
  3. JavaScript學習總結(三)BOM和DOM詳解
  4. JavaScript學習總結(四)function函數部分
  5. JavaScript學習總結(五)原型和原型鏈詳解
  6. JavaScript學習總結(六)數據類型和JSON格式
  7. JavaScript學習總結(七)Ajax和Http狀態字
  8. JavaScript學習總結(八)正則表達式
相關文章
相關標籤/搜索