事件模塊的演變
本篇開始將回顧下Javascript的事件機制。同時會從一個最小的函數開始寫到最后一個具有完整功能的,強大的事件模塊。為敘述方便將響應函數/回調函數/事件Listener/事件handler都稱為事件handler。
先看看頁面中添加事件的幾種方式:
1,直接將JS代碼寫在HTML上
HTML Element元素自身就擁有了很多onXXX屬性,只需將JS代碼賦值給其就可以了。賦值給onXXX的字符串將作為響應函數的函數體(FunctionBody
)。大概這是上世紀90年代的寫法,那時候直接把JS代碼寫在網頁中很普遍,也許那時候的JS并不太重要,只是用來做做驗證或一些花哨的效果而已。
2,定義一個函數,賦值給html元素的onXXX屬性
function clk(){}
</script>
<div onclick="clk()">Div2 Element</div>
先定義函數clk,然后賦值給onclick屬性,這種方式也應該屬于上世紀90年代的流行寫法。比第一種方式好的是它把業務邏輯代碼都封裝在一個函數里了,使HTML代碼與JS代碼稍微有點兒分離,不至于第一種那么緊密耦合。
3,使用element.onXXX方式
<script type="text/javascript">
var d3 = document.getElementById('d3');
d3.onclick = function(){ }
</script>
這種方式也是早期的寫法,但好處是可以將JS與HTML完全分離,前提是需要給HTML元素提供一個額外的id屬性(或其它能獲取該元素對象的方式)。
4,使用addEventListener或attachEvent
<script type="text/javascript">
var d4 = document.getElementById('d4');
function clk(){alert(4)}
if(d4.addEventListener){
d4.addEventListener('click',clk,false);
}
if(d4.attachEvent){
d4.attachEvent('onclick',clk);
}
</script>
這是目前推薦的方式,較前兩種方式功能更為強大,可以為元素添加多個事件handler,支持事件冒泡或捕獲,前三種方式默認都是冒泡。IE6/7/8仍然沒有遵循標準而使用了自己專有的attachEvent,且不支持事件捕獲。
好,把方式4簡單的封裝下, 兼容標準瀏覽器及IE瀏覽器。注意attachEvent的第一個參數需要加上個"on",addEventListener第三個參數為false表示事件冒泡,attachEvent沒有第三個參數,默認就是冒泡,沒有捕獲。
*
* @param {Object} el HTML Element
* @param {Object} type 事件類型
* @param {Object} fn 事件handler
*/
function addEvent(el, type, fn){
if(el.addEventListener){
el.addEventListener(type, fn, false);
}else{
el.attachEvent('on' + type, fn);
}
}
好,用這個工具函數添加一個給document添加一個點擊事件。
alert(this);
alert(arguments[0]);
}
addEvent(document, 'click', handler);
在Firefox等標準瀏覽器中,點擊頁面后將彈出 “[object HTMLDocument]”,及handler中的this就是document自身。但在IE6/7/8中this卻是window對象。這讓人不爽,修改下與標準瀏覽器統一。
if(el.addEventListener){
el.addEventListener(type, fn, false);
}else{
el['e' + fn] = function(){
fn.call(el, window.event);
}
el.attachEvent('on'+type, el['e'+fn]);
}
}