本篇文章主要講解Javascript的事件,如下:
- 事件流
- 如何注冊(cè)和刪除事件
- 跨瀏覽器的事件處理程序和事件對(duì)象
- jquery觸發(fā)事件的幾種方式
事件是什么?
JavaScript與HTML之間的交互是通過(guò)事件實(shí)現(xiàn)的。
事件,就是文檔或?yàn)g覽器窗口中發(fā)生的一些特定交互瞬間,可以使用偵聽(tīng)器(或處理程序)來(lái)預(yù)訂事件,以使事件發(fā)生時(shí)執(zhí)行相應(yīng)的代碼。
事件流是什么?
事件流描述的是從頁(yè)面中接收事件的順序。
目前IE的事件流是事件冒泡流,Netscape的事件流是事件捕獲流。
1、事件冒泡
事件冒泡,即事件開(kāi)始時(shí)由最具體的元素(文檔中嵌套層次最深的那個(gè)節(jié)點(diǎn))接收,然后逐級(jí)向上傳播到較為不具體的節(jié)點(diǎn)。
比如:
···
<body>
<div onclick="handleClick()">Click</div>
</body>
···
點(diǎn)擊div時(shí),click事件首先在div元素上發(fā)生,然后沿DOM樹(shù)向上傳播,在每一級(jí)節(jié)點(diǎn)上都會(huì)發(fā)生,直至傳播到document對(duì)象。傳播順序?yàn)椋?br>
(1)<div>
(2) <body>
(3) <html>
(4) document
所有現(xiàn)代瀏覽器都支持事件冒泡,IE9、Firefox、Chrome和Safari將事件一直冒泡到window對(duì)象。(IE5.5及更早版本中的事件冒泡會(huì)跳過(guò)<html>元素,從<body>直接跳到document)
2、事件捕獲
事件捕獲,是不太具體的節(jié)點(diǎn)更早接收到事件,最具體的節(jié)點(diǎn)最后接收到事件。事件捕獲的用意在于在事件到達(dá)預(yù)定目標(biāo)之前捕獲它。
以上面的click事件為例,document對(duì)象首先接收到cick事件,然后事件沿DOM樹(shù)依次向下,一直傳播到事件的實(shí)際目標(biāo),即<div>元素。
事件捕獲的傳播順序?yàn)椋?br>
(1) document
(2) <html>
(3) <body>
(4) <div>
目前,IE9、Firefox、Chrome和Safari也支持事件捕獲,不過(guò)都是從window對(duì)象開(kāi)始捕獲事件。
總結(jié):IE8只支持事件冒泡,IE9、Firefox、Chrome和Safari既支持事件冒泡也支持事件捕獲。
如何添加事件處理程序(注冊(cè)事件)
1、HTML事件處理程序
元素支持的每種事件,都可以用一個(gè)與相應(yīng)事件處理程序同名的HTML特性指定。這個(gè)特定的值應(yīng)該是能夠執(zhí)行的JavaScript代碼。
如下:
通過(guò)給按鈕指定onclick特性綁定了click事件,當(dāng)點(diǎn)擊按鈕時(shí)就會(huì)執(zhí)行handleClick函數(shù)。其中this為事件的目標(biāo)元素,this.value就是input的value值。
<body>
<input type="button" value="click me" onclick="handleClick(this)">Click</div>
</body>
<script>
function handleClick(){
console.log(this.value); //click me
}
</script>
這種注冊(cè)事件的方式使HTML與JavaScript代碼緊密耦合,如果要更換事件處理程序,既需要修改HTML又需要修改JavaScript,很麻煩。
兼容性:IE8+、chrome、firefox、opera、safari
2、DOM0級(jí)事件處理程序
就是通過(guò)JavaScript注冊(cè)事件,將一個(gè)函數(shù)賦值給一個(gè)事件處理程序?qū)傩?,每個(gè)元素都有自己的事件處理程序?qū)傩裕热鏾nclick,如下:
首先取得要操作的元素對(duì)象的引用,然后給它指定事件處理程序,其中this為當(dāng)前元素
<body>
<input id="btn" type="button" value="click me">Click</div>
</body>
<script>
var btn = document.getElementById('btn');
//綁定事件
btn.onclick = handleClick(){
console.log(this.value); //click me
}
</script>
//將事件處理程序?qū)傩灾翟O(shè)置為null,即刪除事件的綁定
btn.onclick = null;
//
兼容性:IE8+、chrome、firefox、opera、safari
3、DOM2級(jí)事件處理程序
就是使用addEventListener()注冊(cè)事件,removeEventListener()刪除事件addEventListener和removeEventListener都接受三個(gè)參數(shù):要處理的事件名、作為事件處理程序的函數(shù)和一個(gè)布爾值(如果是true,表示在捕獲階段調(diào)用事件處理程序;如果是false,表示在冒泡階段調(diào)用事件處理程序)
注意:
- 用addEventListener注冊(cè)事件,可以為一個(gè)元素同時(shí)添加多個(gè)事件處理程序,并且會(huì)按照他們的添加順序觸發(fā)
- 用addEventListener注冊(cè)事件只能用removeEventListener移除,并且移除時(shí)傳入的參數(shù)必須與注冊(cè)時(shí)相同
<body>
<input id="btn" type="button" value="click me">Click</div>
</body>
<script>
var btn = document.getElementById('btn');
//下面代碼移除事件時(shí)看似傳入的參數(shù)一樣,其實(shí)第二個(gè)參數(shù)是完全不同的兩個(gè)函數(shù)
btn.addEventListener("click", function(){}, false); //添加事件處理程序
btn.removeEventListener("click", function(){}, false); //移除事件處理程序
//正確寫(xiě)法如下:
var handler1 = function() {
console.log(this.value);
};
var handler2 = function(){}
btn.addEventListener("click", handler1, false); //添加事件處理程序handler1
btn.addEventListener("click", handler2, false); //添加事件處理程序handler2
btn.removeEventListener("click", handler1, false); //移除事件處理程序handler1
btn.removeEventListener("click", handler2, false); //移除事件處理程序handle2
</script>
兼容性:IE9+、chrome、firefox、opera、safari
4、IE事件處理程序
就是attachEvent()和detachEvent()來(lái)注冊(cè)事件和刪除事件
attachEvent()和detachEvent()接受兩個(gè)參數(shù):事件處理程序名稱(chēng)和事件處理程序函數(shù)。
由于IE8只支持事件冒泡,所以通過(guò)attachEvent()注冊(cè)事件會(huì)被添加到冒泡階段。
注意:
- attachEvent()的第一個(gè)參數(shù)是"onclick",不是addEventListener中的click
- attachEvent()注冊(cè)事件,是在全局作用域中運(yùn)行,this等于window,而addEventListener注冊(cè)事件是在其所屬元素的作用域內(nèi)運(yùn)行。
- 用attachEvent注冊(cè)事件只能用detachEvent移除,并且移除時(shí)傳入的參數(shù)必須與注冊(cè)時(shí)相同
- 用attachEvent注冊(cè)事件,可以為一個(gè)元素同時(shí)添加多個(gè)事件處理程序,但不是按照添加順序觸發(fā),而是相反順序觸發(fā)
<body>
<input id="btn" type="button" value="click me">Click</div>
</body>
<script>
var btn = document.getElementById('btn');
var handler1 = function() {
console.log(this.value);
};
var handler2 = function(){}
btn.attachEvent("onclick", handler1); //添加事件處理程序handler1
btn.attachEvent("onclick", handler2); //添加事件處理程序handler2
btn.detachEvent("onclick", handler1); //移除事件處理程序handler1
btn.detachEvent("onclick", handler2); //移除事件處理程序handle2
</script>
兼容性:IE和Opera
跨瀏覽器的事件處理程序和事件對(duì)象
以下是以跨瀏覽器的方式處理事件:
var EventUtil = {
//注冊(cè)事件
addHandler: function(element, type, handler) {
if(element.addEventListener) {
element.addEventListener(type, handler, false);
} else if(element.attachEvent) {
element.attachEvent("on" + type, handler);
} else {
element["on" + type] = handler;
}
},
//移除事件
removeHandler: function(element, type, handler) {
if(element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if(element.detachEvent) {
element.detachEvent("on" + type, handler);
} else {
element["on" + type] = null;
}
},
//獲取事件對(duì)象
getEvent: function(event) {
return event ? event : window.event;
},
//獲取目標(biāo)元素
getTarget: function(event) {
return event.target || event.srcElement;
},
//阻止事件默認(rèn)行為
preventDefault: function(event) {
if(event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
},
//阻止冒泡
stopPropagation: function(event) {
if(event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
}
};
jQuery注冊(cè)事件的幾種方式
1、$(selector).click(function);
事件處理程序在元素作用域運(yùn)行,this引用當(dāng)前元素
$(selector). unbind("click"); //移除事件處理程序
2、$(selector).bind('click');
事件處理程序在元素作用域運(yùn)行,this引用當(dāng)前元素,
$(selector). unbind("click"); //移除事件處理程序
3、$(selector).delegate(childSelector, event, data, function);
delegate()方法為指定的元素(屬于被選元素的子元素)添加一個(gè)或多個(gè)事件處理程序。使用delegate()方法的事件處理程序適用于當(dāng)前或者未來(lái)的元素(比如腳本創(chuàng)建的元素)。
如下是為iframe里id為ks-dialog-ok元素添加click事件,id為ks-dialog-ok元素是一個(gè)彈出框的確認(rèn)按鈕,iframe加載完時(shí)id為ks-dialog-ok元素還沒(méi)有渲染,當(dāng)觸發(fā)某個(gè)操作彈出框才會(huì)渲染,所以需要用delegate為未來(lái)的元素綁定事件:
<iframe id="col-web" name="col-web" frameborder="0" width="720px" height="460px" onload="iframeOnload(this)"></iframe>
function iframeOnload(iframe) {
if(iframe.contentWindow.$) {
iframe.contentWindow.$(iframe.contentDocument).delegate("#ks-dialog-ok","click",function() {
$("#flash").hide();
})
}
}
4、$(selector).trigger(event, [param1,param2,...])
trigger() 方法觸發(fā)被選元素的指定事件類(lèi)型
triggerHandler()同trigger(),但是不可以冒泡
如下,當(dāng)點(diǎn)擊button時(shí),就會(huì)觸發(fā)input的文件上傳,當(dāng)覺(jué)得input文件上傳按鈕比較丑時(shí),就可以自定義button按鈕來(lái)覆蓋原來(lái)按鈕,利用trigger觸發(fā)文件上傳
<body>
<button id="btn">點(diǎn)擊</button>
<input type="file">
</body>
<script>
$('#btn').click(function(){
$('input').trigger('click');
})
</script>