有一個需求要為document對象綁定click事件來是想隱藏提示框的交互功能,於是小白寫瞭如下代碼: 同事小銘看了看代碼說: “首先,你為document 綁定了click事件,但是onclick是DOM0級事件,也就是說這種方式綁定的時間相當於為元素綁定了一個時間方法, 所以如果團隊中的其他人再 ...
有一個需求要為document對象綁定click事件來是想隱藏提示框的交互功能,於是小白寫瞭如下代碼:
document.onclick = function(e) { e.preventDefault(); if(e.target !== document.getElementById('myinput')) { hidePageAlert(); } } function hidePageAlert() { //隱藏提示框 }
同事小銘看了看代碼說:
“首先,你為document 綁定了click事件,但是onclick是DOM0級事件,也就是說這種方式綁定的時間相當於為元素綁定了一個時間方法, 所以如果團隊中的其他人再次通過這種方式為document綁定click事件時,就相當於重覆定義了一個方法,會將你定義的click事件方法覆蓋,如下列程式。”
document.onclick= function() { //其他開發人員重新為document綁定時間會覆蓋前面定義的DOM0級click事件 }
“所以你這種方式是很危險的。因此你應該用DOM2級事件處理程式提供的方法addEventListener來實現,然而你知道老版本的IE瀏覽器(低於9)是不支持這個方法的,它支持的是attachEvent,當然如果有不支持DOM2級事件處理程式的瀏覽器,你只能用onclick事件方法來綁定事件。”
“那麼有沒有一個相容所有瀏覽器的方式呢?” 小白追問。
相容模式
// 外觀模式實現 function addEvent(dom, type, fn) { // 對於支持DOM2級事件處理程式addEventListener方法的瀏覽器 if(dom.addEventListener) { dome.addEventListener(type, fn, false); // 對於不支持addEventListener 方法,但是支持attachEvent方法的瀏覽器 }else if(dom.attachEvent) { dom.attachEvent('on' + type, fn); // 對於不支持addEventListener方法也不支持attachEvent方法,但支持on+'事件名'的瀏覽器 }else{ dom['on' + type] = fn; } }
“這樣我們以後對於支持addEventListener 或 attachEvent方法的瀏覽器就可以放心的綁定多個事件了, 如下所示。”
var myInput = document.getElementById('myinput'); addEvent(myInput, 'click', function(){ console.log('綁定第一個事件') }) addEvent(myInput, 'click', function(){ console.log('綁定第二個事件') })
除此之外
“不過之前寫的代碼問題不止一個,之前說了,外觀模式可以簡化底層介面複雜性,也可以解決瀏覽器相容性問題。而你之前寫的代碼除了綁定時間的問題外,另外兩處問題是在其他IE低版本瀏覽器中不相容 e.preventDefault 和 e.target。你也可以通過外觀模式來解決。”
// 獲取事件對象 var getEvent = function(event) { // 標準瀏覽器返回event,IE下window.event return event || window.event; } // 獲取元素 var getTarget = function(event) { var event = getEvent(event); // 標準瀏覽器下event.target, IE下event.srcElement return event.target || event.srcElement; } // 阻止預設行為 var preventDefault = function(event) { var event = getEvent(event); // 標準瀏覽器 if(event.preventDefault) { event.preventDefault(); // IE 瀏覽器 }else { event.returnValue = false; } }
“有了上面的方法,我們就可以用相容的簡單方式來解決上面的問題。”
document.onclick = function(e) { // 阻止預設行為 preventDefault(e); // 獲取事件源目標對象 if(getTarget(e) != document.getElementById('myinput')){ hideInputSug(); } }