要想讓 JavaScript 對用戶的操作作出響應,首先要對 DOM 元素綁定事件處理函數。所謂事件處理函數,就是處理用戶操作的函數,不同的操作對應不同的名稱。
目錄:
-
[1、JavaScript 中事件綁定](#JavaScript 中事件綁定)
-
2、事件冒泡
-
[3、 jQuey中事件綁定](# jQuey中事件綁定)
一. 在DOM元素中直接綁定
#點擊按鈕顯示彈出
<input type="button" onclick="alert('原生函數觸發')" value="點我彈出警告框" />
#或者
<input type="button" onclick="MyAlert()" value="點我彈出警告框" />
<script type="text/javascript">
function MyAlert(){
alert("原生函數觸發");
}
</script>
二. 在JavaScript代碼中綁定
#為 id="demo" 的按鈕綁定一個事件,顯示它的 type 屬性:
<input id="demo" type="button" value="點我顯示 type 屬性" />
<script type="text/javascript">
document.getElementById("demo").onclick=function(){
alert(this.getAttribute("type"));
}
</script>
#解綁事件
document.getElementById("demo").onclick= null;
如果為同一個元素同時綁定多個事件,前面的事件會被后面的事件覆蓋,需指向相同的事件處理函數 **
<body>
<input type="button" value="" id="btn"/>
<script>
//為同一個元素綁定多個不同的事件,指向相同的事件處理函數
document.getElementById("btn").onclick = f1;
document.getElementById("btn").onmouseover = f1;
document.getElementById("btn").onmouseout = f1;
function f1(e) {
switch (e.type) {
case "click":
alert("1");
break;
case "mouseover":
this.style.backgroundColor = "red";
break;
case "mouseout":
this.style.backgroundColor = "green";
break;
}
}
</script>
</body>
三. 綁定事件監聽函數
使用 addEventListener() 或 attachEvent() (兼容ie8)來綁定事件監聽函數。(注:可以綁定多個事件)
addEventListener()函數語法:
elementObject.addEventListener(eventName,handle,useCapture);
參數說明:
- elementObject: DOM對象(即DOM元素)。
- eventName: 事件名稱。注意,這里的事件名稱沒有“ on ”,如鼠標單擊事件 click ,鼠標雙擊事件 doubleclick ,鼠標移入事件 mouseover,鼠標移出事件 mouseout 等。
- handle: 事件句柄函數,即用來處理事件的函數。 (注:函數名,不能帶小括號)
- useCapture: Boolean類型,是否使用捕獲,一般用false 。(默認冒泡)
function f1() {};
function f2() {};
document.getElementById("demo1").addEventListener("click", f1, false);
document.getElementById("demo2").addEventListener("click", f2, false);
//點擊第二個按鈕把第一個按鈕的第一個點擊事件解綁
document.getElementById("demo1").onclick = function () {
//解綁事件的時候,需要在綁定事件的時候,使用命名函數
document.getElementById("demo2").removeEventListener("click", f1, false);
};
attachEvent()函數語法:(不支持捕獲)
elementObject.attachEvent(eventName,handle);
參數說明:
- elementObject: DOM對象(即DOM元素)。
- eventName: 事件名稱。注意,與addEventListener()不同,這里的事件名稱有“ on ”,如鼠標單擊事件 onclick ,鼠標雙擊事件 ondoubleclick ,鼠標移入事件 onmouseover,鼠標移出事件 onmouseout 等。
- handle: 事件句柄函數,即用來處理事件的函數。(注:函數名,不能帶小括號)
function f1() {};
function f2() {};
document.getElementById("demo1").attachEvent("onclick", f1);
document.getElementById("demo2").attachEvent("onclick", f2);
//點擊第二個按鈕把第一個按鈕的第一個點擊事件解綁
document.getElementById("demo1").onclick = function () {
//解綁事件的時候,需要在綁定事件的時候,使用命名函數
document.getElementById("demo2").detachEvent("onclick", f1);
};
addEventListener()是標准的綁定事件監聽函數的方法,是W3C所支持的,Chrome、FireFox、Opera、Safari、IE9.0及其以上版本都支持該函數;但是,IE8.0及其以下版本不支持該方法,它使用attachEvent()來綁定事件監聽函數。所以,這種綁定事件的方法必須要處理瀏覽器兼容問題。
#下面綁定事件的代碼,進行了兼容性處理,能夠被所有瀏覽器支持:
function addEvent(obj,type,handle){
try{ // Chrome、FireFox、Opera、Safari、IE9.0及其以上版本
obj.addEventListener(type,handle,false);
}catch(e){
try{ // IE8.0及其以下版本
obj.attachEvent('on' + type,handle);
}catch(e){ // 早期瀏覽器
obj['on' + type] = handle;
}
}
}
事件冒泡
多個元素嵌套,有層次關系,這些元素都注冊了相同的事件,如果里面的元素的事件觸發了,外面的元素的該事件自動的觸發了
#點擊dv3會一次觸發dv2、dv1
<div id="dv1">
<div id="dv2">
<div id="dv3"></div>
</div>
</div>
<script>
document.getElementById("dv1").onclick = function () {
console.log(this.id);
};
document.getElementById("dv2").onclick = function () {
console.log(this.id);
};
document.getElementById("dv3").onclick = function () {
console.log(this.id);
};
**阻止事件冒泡 **
#window.event.cancelBubble=true;
<script>
document.getElementById("dv1").onclick = function () {
console.log(this.id);
};
document.getElementById("dv2").onclick = function () {
console.log(this.id);
//阻止事件冒泡
// IE特有的,谷歌支持,火狐不支持
window.event.cancelBubble=true;
};
document.getElementById("dv3").onclick = function () {
console.log(this.id);
};
</script>
#e.stopPropagation();
<script>
document.getElementById("dv1").onclick = function () {
console.log(this.id);
};
document.getElementById("dv2").onclick = function (e) {
console.log(this.id);
//阻止事件冒泡
//谷歌和火狐支持
e.stopPropagation();
};
document.getElementById("dv3").onclick = function () {
console.log(this.id);
};
</script>
**事件階段 **
通過e.eventPhase這個屬性可以知道當前的事件是什么階段,一般默認都是冒泡階段,很少用捕獲階段,冒泡階段從里向外,捕獲階段:從外向里
-
1---->捕獲階段
-
2---->目標階段
-
3---->冒泡階段
addEventListener方法的第三個參數是false的時候是冒泡階段
addEventListener方法的第三個參數是true的時候是捕獲階段
<div id="dv1">
<div id="dv2">
<div id="dv3"></div>
</div>
</div>
<script>
//同時注冊點擊事件
var objs = [document.getElementById("dv3"), document.getElementById("dv2"), document.getElementById("dv1")];
//遍歷注冊事件
objs.forEach(function (ele) {
//為每個元素綁定事件
ele.addEventListener("click", function (e) {
console.log(this.id + "====>" + e.eventPhase);
}, false);
});
</script>
#參數false時點擊dv3
dv3====>2,dv2====>3,dv2====>3
#參數true時點擊dv3
dv1====>1,dv2====>1,dv2====>2
jQuery事件綁定
#不具備動態綁定功能,只有點擊原始按鈕才能生成
$("elem").bind('click',function (){ })
$("elem").unbind('click',function (){ })
#委托標簽<a>,為新添加的標簽綁定上事件
$("elem").delegate('a','click',function (){ })
$("elem").undelegate('a','click',function (){ })
#底層on方式
$("#elem").on('click',function(){})
$("#elem").off('click',function(){})
綁定事件on方法是jquery最底層處理方式,也是官方推薦綁定事件的一個方法
基本用法:
*.on( events ,[ selector ] ,[ data ] )*
多個事件綁定同一個函數:
$("#elem").on("mouseover mouseout",function(){ });
多個事件綁定不同函數:
$("#elem").on({
mouseover:function(){},
mouseout:function(){}
});
將數據傳遞到處理程序:
#通過第二參數(對象),當一個事件被觸發時,要傳遞給事件處理函數的
function greet( event ) {
alert( "Hello " + event.data.name ); //Hello example
}
$( "button" ).on( "click", {
name: "example"
}, greet );
針對自己處理機制中,不僅有on方法,還有根據on演變出來的live方法(1.7后廢棄),.delegate()方法等等。這些方法的底層實現部分還是on方法,這是利用了on的另一個事件機制委托的機制衍變而來的。
delegate()委托方法
$('#box').delegate('.button', 'click', function () {
$(this).clone().appendTo('#box');
});
$('#box').undelegate('.button','click');
//支持連綴調用方式
$('div').first().delegate('.button', 'click', function () {
$(this).clone().appendTo('div:first');
});
注意:.delegate()需要指定父元素,然后第一個參數是當前元素,第二個參數是事件方式,第三個參數是執行函數。和.bind()方法一樣,可以傳遞額外參數。.undelegate()和.unbind()方法一樣可以直接刪除所有事件,比如:.undelegate('click')。也可以刪除命名空間的事件,比如:.undelegate('click.abc')。
在DOM 中很多元素綁定相同事件時,或者DOM 中尚不存在即將生成的元素綁定事件時,我們推薦使用事件委托的綁定方式,否則推薦使用.bind()的普通綁定。
底層委托機制:
.on( events ,[ selector ] ,[ data ], handler(eventObject) )
第二參數中提供了一個selector選擇器,簡單的來描述下
<div class="left">
<p class="aaron">
<a>目標節點</a> //點擊在這個元素上
</p>
</div>
$("div").on("click","p",fn)
事件綁定在最上層div元素上,當用戶觸發在a元素上,事件將往上冒泡,一直會冒泡在div元素上。如果提供了第二參數,那么事件在往上冒泡的過程中遇到了選擇器匹配的元素,將會觸發事件回調函數
卸載事件off()方法
根據on綁定事件的一些特性,off方法也可以通過相應的傳遞組合的事件名,名字空間,選擇器或處理函數來移除綁定在元素上指定的事件處理函數。當有多個過濾參數時,只有與這些參數完全匹配的事件處理函數才會被移除。
綁定2個事件:
$("elem").on("mousedown mouseup",fn)
刪除一個事件:
$("elem").off("mousedown")
刪除所有事件:
$("elem").off("mousedown mouseup")
快捷方式刪除所有事件,這里不需要傳遞事件名了,節點上綁定的所有事件講全部銷毀
$("elem").off()
目前綁定事件和解綁的方法有三組共六個。由於這三組的共存可能會造成一定的混亂,為此jQuery1.7 以后推出了.on()和.off()方法徹底摒棄前面三組。
//替代.bind()方式
$('.button').on('click', function () {
alert('替代.bind()');
});
//替代.bind()方式,並使用額外數據和事件對象
$('.button').on('click', {user : 'Lee'}, function (e) {
alert('替代.bind()' + e.data.user);
});
//替代.bind()方式,並綁定多個事件
$('.button').on('mouseover mouseout', function () {
alert('替代.bind()移入移出!');
});
//替代.bind()方式,以對象模式綁定多個事件
$('.button').on({
mouseover : function () {
alert('替代.bind()移入!');
},
mouseout : function () {
alert('替代.bind()移出!');
}
});
//替代.bind()方式,阻止默認行為並取消冒泡
$('form').on('submit', function () {
return false;
});
或
$('form').on('submit', false);
//替代.bind()方式,阻止默認行為
$('form').on('submit', function (e) {
e.preventDefault();
});
//替代.bind()方式,取消冒泡
$('form').on('submit', function (e) {
e.stopPropagation();
});
//替代.unbind()方式,移除事件
$('.button').off('click');
$('.button').off('click', fn);
$('.button').off('click.abc');
//替代.live()和.delegate(),事件委托
$('#box').on('click', '.button', function () {
$(this).clone().appendTo('#box');
});
//替代.die()和.undelegate(),取消事件委托
$('#box').off('click', '.button');
注意:和之前方式一樣,事件委托和取消事件委托也有各種搭配方式,比如額外數據、命名空間等等,這里不在贅述。
不管是.bind()還是.on(),綁定事件后都不是自動移除事件的,需要通過.unbind()和.off()來手工移除。
jQuery 提供了.one()方法,綁定元素執行完畢后自動移除事件,可以方法僅觸發一次的事件。
//類似於.bind()只觸發一次
$('.button').one('click', function () {
alert('one 僅觸發一次!');
});
//類似於.delegate()只觸發一次
$('#box).one('click', 'click', function () {
alert('one 僅觸發一次!');
});