第一百二十一節,JavaScript事件綁定及深刻

JavaScript事件綁定及深刻css

 

 

學習要點:html

1.傳統事件綁定的問題windows

2.W3C事件處理函數瀏覽器

3.IE事件處理函數函數

4.事件對象的其餘補充學習

 

事件綁定分爲兩種:一種是傳統事件綁定(內聯模型,腳本模型),一種是現代事件綁定(DOM2級模型)。現代事件綁定在傳統綁定上提供了更強大更方便的功能。測試

 

一.傳統事件綁定的問題this

傳統事件綁定有內聯模型和腳本模型,內聯模型咱們不作討論,基本不多去用。先來看一下腳本模型,腳本模型將一個函數賦值給一個事件處理函數。spa

window.onload = function () { //window.onload事件,等待html執行完成後,執行匿名函數
    var box = document.getElementById('box');        //獲取元素
    box.onclick = function () {                    //元素點擊觸發事件
        alert('Lee');
    };
};

問題一:一個事件處理函數觸發兩次事件code

若是一個頁面引入兩個js文件,每一個js文件裏都有一個window.onload事件,當兩組程序或兩個JS文件同時執行的時候,後面一個會把前面一個徹底覆蓋掉。致使前面的window.onload徹底失效了。

以下:

window.onload = function () {                //第一組程序項目或第一個JS文件
    alert('Lee');
};

window.onload = function () {                //第二組程序項目或第二個JS文件
    alert('Mr.Lee');
};
//後面一個會把前面一個徹底覆蓋掉。致使前面的window.onload徹底失效了,只能執行到後面這個window.onload

解決覆蓋問題,咱們能夠這樣去解決:

//解決覆蓋問題
window.onload = function () {                //第一個要執行的事件,會被覆蓋
    alert('Lee');
};

if (typeof window.onload == 'function') {        //判斷以前是否有window.onload
    var saved = null;                        //建立一個保存器
    saved = window.onload;                    //把以前的window.onload保存起來
}

window.onload = function () {                //最終一個要執行事件
    if (saved) saved();                        //執行以前一個事件,saved()至關於window.onload = function ()
    alert('Mr.Lee');                            //執行本事件的代碼
};

 

問題二:事件切換器

好比一個元素鼠標點擊後改變顏色,在點擊後又改變顏色,以下

//<div id="box" class="red">測試</div>
// .red{
//     width: 200px;
//     height: 200px;
//     background-color: #ff0f20;
// }
// .blue{
//     width: 200px;
//     height: 200px;
//     background-color: #1516ff;
// }
window.onload = function () { //window.onload事件,等待html執行完成後,執行匿名函數
    var box = document.getElementById('box');        //獲取元素
    box.onclick = toBlue;            //點擊元素後執行toBlue函數
    function toRed() {
        this.className = 'red';    //將元素選擇器設置爲red
        this.onclick = toBlue;        //再次點擊執行toBlue函數
    }

    function toBlue() {
        this.className = 'blue';    //將元素選擇器設置爲blue
        this.onclick = toRed;       //再次點擊執行toRed函數
    }
};

這個切換器在擴展的時候,會出現一些問題:

1.若是增長一個執行函數,那麼會被覆蓋

box.onclick = toAlert;                        //被增長的函數
box.onclick = toBlue;                        //toAlert被覆蓋了

2.若是解決覆蓋問題,就必須包含同時執行,但又出新問題

 

box.onclick = function () {                    //包含進去,但可讀性下降
    toAlert();                                //第一次不會被覆蓋,但第二次又被覆蓋
    toBlue.call(this);                        //還必須把this傳遞到切換器裏
};

 

綜上的三個問題:覆蓋問題、可讀性問題、this傳遞問題。咱們來建立一個自定義的事件處理函數,來解決以上三個問題。

//能夠同時執行多個同一事件函數
addEvent(window, 'onload', function () {            //執行到了
    alert('Lee');
});
addEvent(window, 'onload', function () {            //執行到了
    alert('Mr.Lee');
});

function addEvent(obj, type, fn) {      //能夠同時執行多個同一事件函數,接收3個參數,第一個要綁定事件的對象,第二個事件,第三個事件激發的函數
    var saved = null;                        //設置一個變量,保存每次觸發的事件處理函數
    if (typeof obj[type] == 'function') {    //判斷是否是事件
        saved = obj[type];                //若是有,保存起來
    }
    obj[type] = function () {            //而後執行
        if (saved) saved();                    //執行上一個事件函數
        fn.call(this);                        //冒充addEvent裏的匿名函數,執行函數,把this傳遞過去
    };
}

兩個相同函數名的函數誤註冊了兩次或屢次

PS:以上編寫的自定義事件處理函數,還有一個問題沒有處理,就是兩個相同函數名的函數誤註冊了兩次或屢次,那麼應該把多餘的屏蔽掉。那,咱們就須要把事件處理函數進行遍歷,若是有一樣名稱的函數名就不添加便可。(這裏就不作了),

//兩個相同函數名的函數誤註冊了兩次或屢次
addEvent(window, 'onload', init);                //註冊第一次
addEvent(window, 'onload', init);                //註冊第二次,應該忽略
function init() {
    alert('123');
}


function addEvent(obj, type, fn) {      //能夠同時執行多個同一事件函數,接收3個參數,第一個要綁定事件的對象,第二個事件,第三個事件激發的函數
    var saved = null;                        //設置一個變量,保存每次觸發的事件處理函數
    if (typeof obj[type] == 'function') {    //判斷是否是事件
        saved = obj[type];                //若是有,保存起來
    }
    obj[type] = function () {            //而後執行
        if (saved) saved();                    //執行上一個事件函數
        fn.call(this);                        //冒充addEvent裏的匿名函數,執行函數,把this傳遞過去
    };
}

用自定義事件函數註冊到切換器上查看效果

addEvent(window, 'onload', function () {
    var box = document.getElementById('box');
    addEvent(box, 'onclick', toBlue);
});

function toRed() {
    this.className = 'red';
    addEvent(this, 'onclick', toBlue);
}

function toBlue() {
    this.className = 'blue';
    addEvent(this, 'onclick', toRed);
}


function addEvent(obj, type, fn) {      //能夠同時執行多個同一事件函數,接收3個參數,第一個要綁定事件的對象,第二個事件,第三個事件激發的函數
    var saved = null;                        //設置一個變量,保存每次觸發的事件處理函數
    if (typeof obj[type] == 'function') {    //判斷是否是事件
        saved = obj[type];                //若是有,保存起來
    }
    obj[type] = function () {            //而後執行
        if (saved) saved();                    //執行上一個事件函數
        fn.call(this);                        //冒充addEvent裏的匿名函數,執行函數,把this傳遞過去
    };
}

 

刪除事件處理函數

PS:當你單擊不少不少次切換後,瀏覽器直接卡死,或者彈出一個錯誤:too much recursion(太多的遞歸)。主要的緣由是,每次切換事件的時候,都保存下來,沒有把無用的移除,致使越積越多,最後卡死。

addEvent(window, 'onload', function () {
    var box = document.getElementById('box');
    addEvent(box, 'onclick', toBlue);
});

function toRed() {
    this.className = 'red';
    removeEvent(this,onclick);
    addEvent(this, 'onclick', toBlue);
}

function toBlue() {
    this.className = 'blue';
    removeEvent(this,onclick);
    addEvent(this, 'onclick', toRed);
}


function addEvent(obj, type, fn) {      //能夠同時執行多個同一事件函數,接收3個參數,第一個要綁定事件的對象,第二個事件,第三個事件激發的函數
    var saved = null;                        //設置一個變量,保存每次觸發的事件處理函數
    if (typeof obj[type] == 'function') {    //判斷是否是事件
        saved = obj[type];                //若是有,保存起來
    }
    obj[type] = function () {            //而後執行
        if (saved) saved();                    //執行上一個事件函數
        fn.call(this);                        //冒充addEvent裏的匿名函數,執行函數,把this傳遞過去
    };
}

function removeEvent(obj, type) {   //刪除事件處理函數
    if (obj + [type]) obj[type] = null;         //刪除事件處理函數
}

以上的刪除事件處理函數只不過是一刀切的刪除了,這樣雖然解決了卡死和太多遞歸的問題。但其餘的事件處理函數也一併被刪除了,致使最後得不到本身想要的結果。若是想要只刪除指定的函數中的事件處理函數,那就須要遍歷,查找。(這裏就不作了)

 

二.W3C事件處理函數【重點】

「DOM2級事件」定義了兩個方法,用於添加事件和刪除事件處理程序的操做:addEventListener()和removeEventListener()。全部DOM節點中都包含這兩個方法,而且它們都接受3個參數;事件名、函數、冒泡或捕獲的布爾值(true表示捕獲,false表示冒泡)。

添加和刪除事件

addEventListener()方法,添加事件方法,接受3個參數;事件名、函數、冒泡或捕獲的布爾值(true表示捕獲,false表示冒泡), 注意:傳參事件名稱不加on,IE9如下不支持
使用方式:
元素對象.addEventListener(事件名稱,事件函數,true或false)

1.自動解決覆蓋問題,也就是同時存在兩個相同的事件兩個都能執行,不會覆蓋

//addEventListener()方法,添加事件方法,接受3個參數;事件名、函數、冒泡或捕獲的布爾值(true表示捕獲,false表示冒泡), 注意:傳參事件名稱不加on
window.addEventListener('load', function () {
    alert('Lee');
}, false);
//addEventListener()方法,添加事件方法,接受3個參數;事件名、函數、冒泡或捕獲的布爾值(true表示捕獲,false表示冒泡), 注意:傳參事件名稱不加on
window.addEventListener('load', function () {
    alert('Mr.Lee');
}, false);
//兩個事件都執行了,沒被覆蓋

2.相同事件函數屏蔽問題,也就是一個相同的事件函數重複寫了兩次,會自動屏蔽只執行一次

//addEventListener()方法,添加事件方法,接受3個參數;事件名、函數、冒泡或捕獲的布爾值(true表示捕獲,false表示冒泡), 注意:傳參事件名稱不加on
window.addEventListener('load',lik, false);  //一個相同的事件函數重複寫了兩次,會自動屏蔽只執行一次
window.addEventListener('load',lik, false);
function lik(){
    alert('測試')
}

 

removeEventListener()方法,刪除指定的事件方法,接受3個參數,參數和addEventListener建立事件時同樣,第一個是建立事件時的事件名稱,第二個是建立事件時的執行函數,第三個是冒泡或捕獲的布爾值(true表示捕獲,false表示冒泡), 注意:傳參事件名稱不加on,用於一個事件使用完畢後將事件刪除,IE9如下不支持
使用方式:
建立事件時元素對象.removeEventListener(建立事件時的事件名稱,建立事件時的執行事件函數,true或false)

3.能夠經過addEventListener方法將對象的this傳到執行函數裏,執行函數裏的this就是表明事件對象自己

//addEventListener()方法,添加事件方法,接受3個參數;事件名、函數、冒泡或捕獲的布爾值(true表示捕獲,false表示冒泡), 注意:傳參事件名稱不加on
window.addEventListener('load', function () {  //等待頁面加載完後,執行匿名函數
    var box = document.getElementById('box');  //經過ID獲取元素節點
    box.addEventListener('click',toBlue , false);  //將獲取到的節點綁定一個點擊事件,點擊執行toBlue函數
}, false);

function toRed() {
    //此時這裏的this代碼對象自己box,經過addEventListener()函數傳遞過來
    this.className = 'red'; //改變對象class屬性值
    this.removeEventListener('click', toRed, false);  //這次事件使用完畢,刪除這次事件,參數與建立時同樣
    this.addEventListener('click', toBlue, false);  //給對象建立一個點擊事件,點擊後執行toBlue函數
}

function toBlue() {
    //此時這裏的this代碼對象自己box,經過addEventListener()函數傳遞過來
    this.className = 'blue'; //改變對象class屬性值
    this.removeEventListener('click', toBlue, false);  //這次事件使用完畢,刪除這次事件,參數與建立時同樣
    this.addEventListener('click', toRed, false);  //給對象建立一個點擊事件,點擊後執行toRed函數
}

 4.添加一個額外的事件,會不會被覆蓋,或者只能執行一次

//addEventListener()方法,添加事件方法,接受3個參數;事件名、函數、冒泡或捕獲的布爾值(true表示捕獲,false表示冒泡), 注意:傳參事件名稱不加on
window.addEventListener('load', function () {  //等待頁面加載完後,執行匿名函數
    var box = document.getElementById('box');  //經過ID獲取元素節點

    //添加一個額外的事件,會不會被覆蓋,或者只能執行一次
    box.addEventListener('click',function () {  //添加一個事件,不會被覆蓋
        alert('添加');
    },false);

    box.addEventListener('click',toBlue , false);  //將獲取到的節點綁定一個點擊事件,點擊執行toBlue函數
}, false);

function toRed() {
    //此時這裏的this代碼對象自己box,經過addEventListener()函數傳遞過來
    this.className = 'red'; //改變對象class屬性值
    this.removeEventListener('click', toRed, false);  //這次事件使用完畢,刪除這次事件,參數與建立時同樣
    this.addEventListener('click', toBlue, false);  //給對象建立一個點擊事件,點擊後執行toBlue函數
}

function toBlue() {
    //此時這裏的this代碼對象自己box,經過addEventListener()函數傳遞過來
    this.className = 'blue'; //改變對象class屬性值
    this.removeEventListener('click', toBlue, false);  //這次事件使用完畢,刪除這次事件,參數與建立時同樣
    this.addEventListener('click', toRed, false);  //給對象建立一個點擊事件,點擊後執行toRed函數
}

設置冒泡和捕獲階段

以前咱們上一章瞭解了事件冒泡,即從裏到外觸發。咱們也能夠經過event對象來阻止某一階段的冒泡。那麼W3C現代事件綁定能夠設置冒泡和捕獲。

//addEventListener()方法,添加事件方法,接受3個參數;事件名、函數、冒泡或捕獲的布爾值(true表示捕獲,false表示冒泡), 注意:傳參事件名稱不加on
window.addEventListener('load', function () {  //等待頁面加載完後,執行匿名函數
    var box = document.getElementById('box');  //經過ID獲取元素節點
    document.addEventListener('click', function () {  //建立一個點擊事件
        alert('document');
    }, true);                                    //把布爾值設置成true,則爲捕獲,從外向裏激發,設爲false爲冒泡,從裏向爲激發
    box.addEventListener('click', function () {  //建立一個點擊事件
        alert('div');
    }, true);
}, false);

綜上所述:w3c是比較完美的解決了傳統事件出現的一些問題,可是IE9如下不支持,IE9如下采用了本身的事件

 

三.IE事件處理函數【不推薦使用】

IE實現了與DOM中相似的兩個方法:attachEvent()和detachEvent()。這兩個方法接受相同的參數:事件名稱和函數。

在使用這兩組函數的時候,先把區別說一下:

1.IE不支持捕獲,只支持冒泡;

2.IE添加事件不能屏蔽重複的函數;

3.IE中的this指向的是window而不是DOM對象。

4.在傳統事件上,IE是沒法接受到event對象的,但使用了attchEvent()卻能夠,但有些區別。

 

attachEvent()方法,IE添加事件方法,接受2個參數,第一個事件名稱,第二個事件函數,除IE外不支持
使用方式:
元素對象.attachEvent(事件名稱,事件函數)


detachEvent()方法,IE方法,刪除一個attachEvent添加的事件,接受2個參數,第一個添加事件時的事件名稱,第二個添加事件時的事件函數,除IE外不支持
使用方式:
元素對象.detachEvent(添加事件時的事件名稱,添加事件時的事件函數)

//建立事件.等頁面執行完畢後,執行匿名函數
window.attachEvent('onload',function () {
    //經過ID獲取到元素
    var box = document.getElementById('box');
    //給元素添加一個點擊事件,點擊後執行toBlue函數
    box.attachEvent('onclick',toBlue);

});


function toRed() {
    //獲取事件的event對象,經過event對象獲取到當前元素節點
    var that = window.event.srcElement;
    //將元素的class屬性值設置爲red
    that.className = 'red';
    //刪除上一個建立的對象
    that.detachEvent('onclick', toRed);
    //給元素建立一個點擊事件,點擊後執行toBlue函數
    that.attachEvent('onclick', toBlue);
}

function toBlue() {
    //獲取事件的event對象,經過event對象獲取到當前元素節點
    var that = window.event.srcElement;
    //將元素的class屬性值設置爲blue
    that.className = 'blue';
    //刪除上一個建立的對象                      detachEvent()方法,IE方法,刪除一個attachEvent添加的事件,接受2個參數,第一個添加事件時的事件名稱,第二個添加事件時的事件函數,
    that.detachEvent('onclick', toBlue);
    //給元素建立一個點擊事件,點擊後執行toRed函數
    that.attachEvent('onclick', toRed);
}

 誇瀏覽器自定義建立事件,自定義移除事件,自定義獲取目標,用自定義寫一個完整的切換器 【但不推薦,下面會說明】

//建立事件,等頁面執行完畢後執行匿名函數
addEvent(window,'load',function () {
    //經過ID獲取到元素
    var box = document.getElementById('box');
    //給元素建立一個點擊事件,點擊後執行toBlue函數
    addEvent(box,'click',toBlue);

});

//切換器
function toBlue(evt) {
    //獲取事件的event對象,經過event對象獲取到當前元素節點
    var that = getTarget(evt);
    //將元素的class屬性值設置爲blue
    that.className = 'blue';
    //刪除上一個建立的對象                      detachEvent()方法,IE方法,刪除一個attachEvent添加的事件,接受2個參數,第一個添加事件時的事件名稱,第二個添加事件時的事件函數,
    removeEvent(that,'click',toBlue);
    //給元素建立一個點擊事件,點擊後執行toRed函數
    addEvent(that,'click',toRed)
}

function toRed(evt) {
    //獲取事件的event對象,經過event對象獲取到當前元素節點
    var that = getTarget(evt);
    //將元素的class屬性值設置爲blue
    that.className = 'red';
    //刪除上一個建立的對象                      detachEvent()方法,IE方法,刪除一個attachEvent添加的事件,接受2個參數,第一個添加事件時的事件名稱,第二個添加事件時的事件函數,
    removeEvent(that,'click',toRed);
    //給元素建立一個點擊事件,點擊後執行toRed函數
    addEvent(that,'click',toBlue)
}



//跨瀏覽器添加事件,添加事件兼容
function addEvent(obj, type, fn) {     //添加事件函數,接收3個參數,1事件對象,2事件名稱,3事件函數
    //判斷瀏覽器若是支持w3c
    if (obj.addEventListener) {
        //就用w3c的addEventListener方法添加對象,將事件名稱和事件函數傳入添加事件
        obj.addEventListener(type, fn, false);
    } else if (obj.attachEvent) {   //判斷若是瀏覽器是IE9如下,就用IE的方法attachEvent添加事件
        //將事件名稱和事件函數傳入建立對象
        obj.attachEvent('on' + type, fn);
    }
}

//跨瀏覽器移除事件,移除事件兼容
function removeEvent(obj, type, fn) {    //移除事件函數,接收3個參數,1事件對象,2事件名稱,3事件函數
    //判斷瀏覽器若是支持w3c
    if (obj.removeEventListener) {
        //就用w3c的removeEventListener方法移除對象,將事件名稱和事件函數傳入移除事件
        obj.removeEventListener(type, fn, false);
    } else if (obj.detachEvent) {      //判斷若是瀏覽器是IE9如下,就用IE的方法detachEvent移除事件
        //將事件名稱和事件函數傳入移除對象
        obj.detachEvent('on' + type, fn);
    }
}

//跨瀏覽器獲取事件目標,獲取事件目標兼容
function getTarget(evt) {    //參數接收event對象
    //判斷若是瀏覽器支持w3c獲取event對象
    if (evt.target) {
        //返回獲取到的event對象裏的標籤節點,也就是目標
        return evt.target;
    } else if (window.event.srcElement) {   //若是是IE瀏覽器
        //返回IE方式獲取到的event對象裏的標籤節點,也就是目標
        return window.event.srcElement;
    }
}

PS:IE中的事件綁定函數attachEvent()和detachEvent()可能在實踐中不去使用,有幾個緣由:1.IE9就將全面支持W3C中的事件綁定函數;2.IE的事件綁定函數沒法傳遞this;3.IE的事件綁定函數不支持捕獲;4.同一個函數註冊綁定後,沒有屏蔽掉;5.有內存泄漏的問題。至於怎麼替代,咱們將在之後的項目課程中探討。

 

 

四.事件對象的其餘補充

在W3C提供了一個屬性:relatedTarget;這個屬性能夠在onmouseover和onmouseout事件中獲取從哪裏移入和從哪裏移出的DOM對象。

relatedTarget屬性,能夠在onmouseover事件和onmouseout事件中獲取鼠標從哪裏移入和從哪裏移出的DOM對象。也就是鼠標移動後獲取當前對象最近的一個對象,IE9如下不支持

使用方式:
event對象.relatedTarget

// <span class="adc">
// <div id="box" class="red">測試</div>
// </span>

//等待頁面加載完成後執行匿名函數
window.onload =  function () {
    //經過ID獲取到元素對象
    var box = document.getElementById('box');
    //給元素添加一個事件,當鼠標移入後激發函數
    box.onmouseover = function (evt) {  //接收事件傳遞的event對象
        //relatedTarget屬性,能夠在onmouseover事件和onmouseout事件中獲取鼠標從哪裏移入和從哪裏移出的DOM對象。也就是鼠標移動後獲取當前對象最近的一個對象
        alert(evt.relatedTarget.tagName);
        //返回:span
    }
};

當鼠標移出後激發

// <span class="adc">
// <div id="box" class="red">測試</div>
// </span>

//等待頁面加載完成後執行匿名函數
window.onload =  function () {
    //經過ID獲取到元素對象
    var box = document.getElementById('box');
    //給元素添加一個事件,當鼠標移出後激發函數
    box.onmouseout = function (evt) {  //接收事件傳遞的event對象
        //relatedTarget屬性,能夠在onmouseover事件和onmouseout事件中獲取鼠標從哪裏移入和從哪裏移出的DOM對象。也就是鼠標移動後獲取當前對象最近的一個對象
        alert(evt.relatedTarget.tagName);
        //返回:span
    }
};

 

IE提供了兩組分別用於移入移出的屬性:fromElement獲取移入最近對象和toElement獲取移出最近對象,分別對應onmouseover和onmouseout。

fromElement屬性,IE屬性,對應onmouseover事件,獲取移入最近對象
使用方式:
event對象.fromElement

// <span class="adc">
// <div id="box" class="red">測試</div>
// </span>

//等待頁面加載完成後執行匿名函數
window.onload =  function () {
    //經過ID獲取到元素對象
    var box = document.getElementById('box');
    //給元素添加一個事件,當鼠標移入後激發函數
    box.onmouseover = function () {
        //fromElement屬性,IE屬性,對應onmouseover事件,獲取移入最近對象
        alert(window.event.fromElement.tagName);  //接收事件傳遞的event對象
        //返回:span
    }
};

toElement屬性,IE屬性,對應onmouseout事件,獲取移出最近對象
使用方式:
event對象.toElement

// <span class="adc">
// <div id="box" class="red">測試</div>
// </span>

//等待頁面加載完成後執行匿名函數
window.onload =  function () {
    //經過ID獲取到元素對象
    var box = document.getElementById('box');
    //給元素添加一個事件,當鼠標移出後激發函數
    box.onmouseout = function () {
        //toElement屬性,IE屬性,對應onmouseout事件,獲取移出最近對象
        alert(window.event.toElement.tagName);  //接收事件傳遞的event對象
        //返回:span
    }
};

PS:fromElement和toElement若是分別對應相反的鼠標事件,沒有任何意義。

 

根據IE和w3c作兼容,自定義跨瀏覽器兼容獲取事件最近對象

// <span class="adc">
// <div id="box" class="red">測試</div>
// </span>

//等待頁面加載完成後執行匿名函數
window.onload =  function () {
    //經過ID獲取到元素對象
    var box = document.getElementById('box');
    //給元素添加一個事件,當鼠標移入後激發函數
    box.onmouseover = function (evt) { //接收事件傳遞的event對象
        //執行自定義函數獲取鼠標移入或者移出最近對象
        alert(getTarget(evt).tagName);  //將event對象傳入自定義函數
        //返回:span
    }
};

//作的就是跨瀏覽器兼容操做:
function getTarget(evt) {
    //若是evt執行不成功,說明是IE9如下的IE瀏覽器就執行window.event獲取event對象
    var e = evt || window.event;                //獲得事件對象
    if (e.srcElement) {                        //若是支持srcElement獲取事件對象而且,表示IE
        if (e.type == 'mouseover') {            //若是事件屬性是鼠標移入
            return e.fromElement;            //就使用fromElement返回最近對象
        } else if (e.type == 'mouseout') {        //若是事件屬性是鼠標移入
            return e.toElement;                //就使用toElement返回最近對象
        }
    } else if (e.relatedTarget) {                //若是支持relatedTarget,表示W3C
        return e.relatedTarget;  //經過relatedTarget返回最近對象
    }
}

 

 阻止瀏覽器超連接默認行爲,也就是阻止瀏覽器默認的鏈接跳轉

有時咱們須要阻止事件的默認行爲,好比:一個超連接的默認行爲就點擊而後跳轉到指定的頁面。那麼阻止默認行爲就能夠屏蔽跳轉的這種操做,而實現自定義操做。

傳統方式屏蔽超連接跳轉【不推薦】

//<a href="http://www.baidu.com">百度</a>

//等待頁面加載完成後執行匿名函數
window.onload =  function () {
    //經過元素名稱獲取到目標元素對象
    var link = document.getElementsByTagName('a')[0];
    //給元素對象添加一個點擊事件,點擊後執行函數
    link.onclick = function () {
        //返回假,屏蔽元素跳轉,也就是屏蔽掉超連接跳轉
        return false;
    }
};

PS:雖然return false;能夠實現這個功能,但有漏洞;第一:必須寫到最後,這樣致使中間的代碼執行後,有可能執行不到return false;第二:return false寫到最前那麼以後的自定義操做就失效了。因此,最好的方法應該是在最前面就阻止默認行爲,而且後面還能執行代碼。

preventDefault()方法,W3C,阻止默認行爲,阻止超連接跳轉,但ie9如下不支持
使用方式:
event對象.preventDefault()

//<a href="http://www.baidu.com">百度</a>

//等待頁面加載完成後執行匿名函數
window.onload =  function () {
    //經過元素名稱獲取到目標元素對象
    var link = document.getElementsByTagName('a')[0];
    //給元素對象添加一個點擊事件,點擊後執行函數
    link.onclick = function (evt) {
        evt.preventDefault();   //W3C,阻止默認行爲,阻止超連接跳轉,但ie9如下不支持
    }
};

 

returnValue屬性,IE阻止默認行爲,阻止超連接跳轉,只支持IE9如下
使用方式:
event對象.returnValue = false

//<a href="http://www.baidu.com">百度</a>

//等待頁面加載完成後執行匿名函數
window.onload =  function () {
    //經過元素名稱獲取到目標元素對象
    var link = document.getElementsByTagName('a')[0];
    //給元素對象添加一個點擊事件,點擊後執行函數
    link.onclick = function () {
        window.event.returnValue = false;  //returnValue屬性,IE阻止默認行爲,阻止超連接跳轉,只支持IE
    }
};

 

跨瀏覽器兼容,阻止默認行爲,阻止超連接跳轉

//<a href="http://www.baidu.com">百度</a>

//等待頁面加載完成後執行匿名函數
window.onload =  function () {
    //經過元素名稱獲取到目標元素對象
    var link = document.getElementsByTagName('a')[0];
    //給元素對象添加一個點擊事件,點擊後執行函數
    link.onclick = function (evt) {
        preDef(evt);  //執行函數跨瀏覽器兼容,阻止超連接跳轉,將event對象傳入
    }
};

//跨瀏覽器兼容,跨瀏覽器兼容,阻止默認行爲,阻止超連接跳轉
function preDef(evt) { //接收event對象
    //若是不能執行evt,說明是IE瀏覽器就用window.event獲取event對象
    var e = evt || window.event;
    //判斷W3C,阻止默認行爲,若是爲真
    if (e.preventDefault) {
        //就用W3C,阻止默認行爲
        e.preventDefault();
    } else {
        //不然就用ie的屬性returnValue阻止行爲
        e.returnValue = false;
    }
}

 

上下文菜單事件:oncontextmenu,當咱們右擊網頁的時候,會自動出現windows自帶的菜單。那麼咱們可使用oncontextmenu事件來修改咱們指定的菜單,但前提是把右擊的默認行爲取消掉。

oncontextmenu事件,oncontextmenu事件用來修改咱們指定的菜單,但前提是把右擊的默認行爲取消掉。
使用方式:
對象.oncontextmenu.執行函數

//HTML代碼
/*
<textarea id="wb" placeholder="請輸入您的內容"></textarea>
<ul id="cd">
    <li>菜單1</li>
    <li>菜單2</li>
    <li>菜單3</li>
</ul>
 */

//css代碼
/*
#wb{
    width: 400px;
    height: 400px;
}
#cd{
    width: 100px;
    height: 100px;
    background-color: #b2bbff;
    display: none;
}
 */

//等待頁面加載完成後執行匿名函數
addEvent(window,'load',function () {
    //經過ID獲取到文本框
    var wb = document.getElementById('wb');
    //給文本框添加一個菜單事件
    addEvent(wb,'contextmenu',function (evt) {
        preDef(evt); //執行自定義函數,屏蔽了瀏覽器默認菜單
        //經過ID獲取到菜單ul標籤
        var cd = document.getElementById('cd');
        //將標籤的style屬性設置一個值,display = 'block',將區塊顯示出來
        cd.style.display = 'block';
        //若是不能執行evt,說明是IE瀏覽器就用window.event獲取event對象
        var e = evt || window.event;
        //經過event對象獲取鼠標座標,將座標設置成css定位的位置
        cd.style.left = e.clientX + 'px';
        //經過event對象獲取鼠標座標,將座標設置成css定位的位置
        cd.style.top = e.clientX + 'px';
        //在根元素建立一個點擊事件,當點擊鼠標左鍵時隱藏菜單區塊
        addEvent(document,'click',function () {
            cd.style.display = 'none';
        })
    })
});

//跨瀏覽器添加事件,添加事件兼容
function addEvent(obj, type, fn) {     //添加事件函數,接收3個參數,1事件對象,2事件名稱,3事件函數
    //判斷瀏覽器若是支持w3c
    if (obj.addEventListener) {
        //就用w3c的addEventListener方法添加對象,將事件名稱和事件函數傳入添加事件
        obj.addEventListener(type, fn, false);
    } else if (obj.attachEvent) {   //判斷若是瀏覽器是IE9如下,就用IE的方法attachEvent添加事件
        //將事件名稱和事件函數傳入建立對象
        obj.attachEvent('on' + type, fn);
    }
}


//跨瀏覽器兼容,阻止默認行爲
function preDef(evt) { //接收event對象
    //若是不能執行evt,說明是IE瀏覽器就用window.event獲取event對象
    var e = evt || window.event;
    //判斷W3C,阻止默認行爲,若是爲真
    if (e.preventDefault) {
        //就用W3C,阻止默認行爲
        e.preventDefault();
    } else {
        //不然就用ie的屬性returnValue阻止行爲
        e.returnValue = false;
    }
}

PS:oncontextmenu事件很經常使用,這直接致使瀏覽器兼容性較爲穩定。

 

 

卸載前事件:onbeforeunload,這個事件能夠幫助在離開本頁的時候給出相應的提示,「離開」或者「返回」操做。

onbeforeunload事件,這個事件能夠幫助在離開本頁的時候給出相應的提示,「離開」或者「返回」操做。
使用方式:
對象.onbeforeunload.執行函數

 

//當用戶離開當前頁面時激發函數
addEvent(window,'beforeunload',function (evt) {
    //屏蔽當前對象的默認行爲
    preDef(evt);
});

//跨瀏覽器添加事件,添加事件兼容
function addEvent(obj, type, fn) {     //添加事件函數,接收3個參數,1事件對象,2事件名稱,3事件函數
    //判斷瀏覽器若是支持w3c
    if (obj.addEventListener) {
        //就用w3c的addEventListener方法添加對象,將事件名稱和事件函數傳入添加事件
        obj.addEventListener(type, fn, false);
    } else if (obj.attachEvent) {   //判斷若是瀏覽器是IE9如下,就用IE的方法attachEvent添加事件
        //將事件名稱和事件函數傳入建立對象
        obj.attachEvent('on' + type, fn);
    }
}


//跨瀏覽器兼容,阻止默認行爲
function preDef(evt) { //接收event對象
    //若是不能執行evt,說明是IE瀏覽器就用window.event獲取event對象
    var e = evt || window.event;
    //判斷W3C,阻止默認行爲,若是爲真
    if (e.preventDefault) {
        //就用W3C,阻止默認行爲
        e.preventDefault();
    } else {
        //不然就用ie的屬性returnValue阻止行爲
        e.returnValue = false;
    }
}

 

鼠標滾輪(mousewheel)和DOMMouseScroll,用於獲取鼠標上下滾輪的距離。

onmousewheel事件,當用戶滾動鼠標滾輪時激發函數,非火狐
wheelDelta屬性,用於獲取鼠標上下滾輪的距離,非火狐

//當用戶滾動鼠標滾輪時激發函數
addEvent(document,'mousewheel',function (evt) {  //非火狐
    //若是不能執行evt,說明是IE瀏覽器就用window.event獲取event對象
    var e = evt || window.event;
    //獲取鼠標滾輪滾動的距離
    alert(e.wheelDelta);
});

//跨瀏覽器添加事件,添加事件兼容
function addEvent(obj, type, fn) {     //添加事件函數,接收3個參數,1事件對象,2事件名稱,3事件函數
    //判斷瀏覽器若是支持w3c
    if (obj.addEventListener) {
        //就用w3c的addEventListener方法添加對象,將事件名稱和事件函數傳入添加事件
        obj.addEventListener(type, fn, false);
    } else if (obj.attachEvent) {   //判斷若是瀏覽器是IE9如下,就用IE的方法attachEvent添加事件
        //將事件名稱和事件函數傳入建立對象
        obj.attachEvent('on' + type, fn);
    }
}

 

 

onDOMMouseScroll事件,當用戶滾動鼠標滾輪時激發函數,火狐
detail屬性,用於獲取鼠標上下滾輪的距離,火狐

//當用戶滾動鼠標滾輪時激發函數
addEvent(document,'DOMMouseScroll',function (evt) {  
    //若是不能執行evt,說明是IE瀏覽器就用window.event獲取event對象
    var e = evt || window.event;
    //獲取鼠標滾輪滾動的距離
    alert(evt.detail * 30);
});

//跨瀏覽器添加事件,添加事件兼容
function addEvent(obj, type, fn) {     //添加事件函數,接收3個參數,1事件對象,2事件名稱,3事件函數
    //判斷瀏覽器若是支持w3c
    if (obj.addEventListener) {
        //就用w3c的addEventListener方法添加對象,將事件名稱和事件函數傳入添加事件
        obj.addEventListener(type, fn, false);
    } else if (obj.attachEvent) {   //判斷若是瀏覽器是IE9如下,就用IE的方法attachEvent添加事件
        //將事件名稱和事件函數傳入建立對象
        obj.attachEvent('on' + type, fn);
    }
}

 

 

瀏覽器兼容

//當用戶滾動鼠標滾輪時激發函數
addEvent(document,'DOMMouseScroll',function (evt) {  //火狐
    alert(getWD(evt));    //執行自定義函數
});
addEvent(document,'mousewheel',function (evt) {  //非火狐
    alert(getWD(evt));    //執行自定義函數
});
//跨瀏覽器添加事件,添加事件兼容
function addEvent(obj, type, fn) {     //添加事件函數,接收3個參數,1事件對象,2事件名稱,3事件函數
    //判斷瀏覽器若是支持w3c
    if (obj.addEventListener) {
        //就用w3c的addEventListener方法添加對象,將事件名稱和事件函數傳入添加事件
        obj.addEventListener(type, fn, false);
    } else if (obj.attachEvent) {   //判斷若是瀏覽器是IE9如下,就用IE的方法attachEvent添加事件
        //將事件名稱和事件函數傳入建立對象
        obj.attachEvent('on' + type, fn);
    }
}

//自定義獲取鼠標滾動的距離,瀏覽器兼容
function getWD(evt) {   //event對象
    //若是不能執行evt,說明是IE瀏覽器就用window.event獲取event對象
    var e = evt || window.event;
    //若是不是IE用wheelDelta獲取距離
    if (e.wheelDelta) {
        return e.wheelDelta;
    } else if (e.detail) {  //若是是IE用detail獲取距離
        return -evt.detail * 30;
    }
}

PS:經過瀏覽器檢測能夠肯定火狐只執行DOMMouseScroll

DOMContentLoaded事件和readystatechange事件,有關DOM加載方面的事件,關於這兩個事件的內容很是多且繁雜,咱們先點明在這裏,在項目課程中使用的時候詳細討論。

相關文章
相關標籤/搜索