我們都知道,在javascript的DOM操作中,事件監(jiān)聽器與內(nèi)聯(lián)事件這兩個(gè)方法可以實(shí)現(xiàn)相同的功能,那到底他們有何區(qū)別呢?
事件監(jiān)聽器Event Listeners (addEventListener and IE's attachEvent)
<pre>
element.attachEvent()只能使用于IE8及以下瀏覽器;
element.attachEvent('onclick', function() { /* do stuff here*/ });
</pre>
在大多數(shù)其它的其它瀏覽器包括IE9+,你可以按如下格式使用:
element.addEventListener('click', function() { /* do stuff here*/ }, false);
通過這種方式(DOM Level 2 events),我們可以附加無(wú)限個(gè)事件到同一個(gè)元素,唯一限制我們的就是客戶端的內(nèi)存和其它相關(guān)瀏覽器相關(guān)的性能了。
這種方式我們可以靈活地使用anonymous function、function reference或“閉包”:
<pre>
var myFunctionReference = function() { /* do stuff here*/ }
element.attachEvent('onclick', myFunctionReference);
element.addEventListener('click', myFunctionReference , false);
</pre>
另一個(gè)重要的addEventListener的特點(diǎn)是最后一個(gè)參數(shù),用來控制事件監(jiān)聽器是如何來響應(yīng)事件的傳播機(jī)制的(也就是說是否啟用capture)。當(dāng)然,我用的是false在上例中,意思是不使用capture用bubble式,默認(rèn)的方式,也是約95%的案例所用的處理方式。
但這個(gè)參數(shù)對(duì)于attachEvent()或元素內(nèi)聯(lián)事件inline events來說卻并沒有一個(gè)相應(yīng)的參數(shù)來處理。
元素的內(nèi)聯(lián)事件Inline events
Ex:
(HTML onclick="" property and element.onclick)
大多數(shù)主流的瀏覽器支持內(nèi)聯(lián)事件Inline event中執(zhí)行javascript代碼,我們可以放置一個(gè)事件監(jiān)聽器event listener到元素的屬性上,類似如下:
<a id="testing" href="#" onclick="alert('did stuff inline');">Click me</a>
大多數(shù)有經(jīng)驗(yàn)的開發(fā)者會(huì)盡量避開這種方式,但他確實(shí)能達(dá)到想要的效果;
因?yàn)樗?jiǎn)單粗暴直接。
在此處,你可以不用“閉包”和匿名函數(shù)anonymous functions(盡管從類別上來說這個(gè)處理器自身就是一個(gè)匿名函數(shù)),因?yàn)槟隳芸刂频淖饔糜蚴怯邢拗频摹?/p>
另一種方法是:
element.onclick = function () { /*do stuff here */ };
這種方法其實(shí)是等價(jià)于上面的內(nèi)聯(lián)事件的,只不過內(nèi)聯(lián)javascript希望能夠使得你能有更多的作用域方面的控制(因此,你可以編寫一個(gè)JavaScript腳本,而不是只有HTML)而且能夠使用匿名函數(shù)、函數(shù)引用和“閉包”。
不過,相比以上方式的簡(jiǎn)單直接而言他們最大的缺點(diǎn)就非常突出了,我們可以也僅僅只可以添加一個(gè)內(nèi)聯(lián)事件,因?yàn)閮?nèi)聯(lián)事件是作為元素的特性/屬性attribute/property來存儲(chǔ)在元素element上的,也就是說,元素的屬性是可以覆寫的.
看下例:
<pre>
var element = document.getElementById('testing');
element.onclick = function () { alert('did stuff #1'); };
element.onclick = function () { alert('did stuff #2'); };
</pre>
我們點(diǎn)擊element元素時(shí),可以看到僅僅只有"Did stuff #2"生效,因?yàn)榈诙€(gè)值覆蓋了第一個(gè)分配的值,而且,同時(shí)我們也覆蓋了元素原生的內(nèi)聯(lián)HTML的onclick特性/屬性property,具體參看: http://jsfiddle.net/jpgah/
哪一種更好?
這個(gè)問題關(guān)乎瀏覽器兼容性的需要以及我們自身的需要,是否我們真的需要附加多個(gè)事件到同一個(gè)元素上呢?是否我們的項(xiàng)目更具前瞻性,可以用更超前的方式?如果是attachEvent()和addEventListener()都可以考慮,如果不是,一個(gè)小小的內(nèi)聯(lián)元素inline event也能搞惦這個(gè)把戲。
不過jQuery和一些其它類似的javascript框架已經(jīng)把這些問題打包成了通用的解決方案了,同樣的代碼用jQuery來實(shí)現(xiàn)就很簡(jiǎn)單了,而且所有的不同類型的瀏覽器都兼容:
$(element).on('click', function () { /* do stuff */ });
最后,不要試著用一種方式來做這個(gè)事情,我們可以小改動(dòng)一下來照顧一下老版本的瀏覽器:
function addEvent(element, evnt, funct){
if (element.attachEvent)
return element.attachEvent('on'+evnt, funct);
else
return element.addEventListener(evnt, funct, false);
}
// example
addEvent(document.getElementById('myElement'),'click',function () { alert('hi!'); }
);