在jQuery1.9版本中,已經去掉了live和delegate方法,從而將on方法的地位進一步提升。
jQuery如此推崇on方法,必有其牛逼的地方。那麼我們就有必要了解這個on,並在代碼中利用它,從而優化代碼和提高性能。
一、on之基本使用方法注:在jQuery1.7後,on方法就可以全面綁定任何事件了。
.on( events [,selector] [,data] ,handler)
event:為事件類型,可以有多個事件類型。
selector:可選,過濾綁定在on方法上的後代元素。注:如果有selector,on方法是采用事件代理,這樣可以提升代碼性能。
data:可選,當事件被觸發時,它會傳給event.data,從而可以加以利用
handler:當事件被觸發時,執行的方法。
下面寫個demo,看看on的使用:
//當p元素的click事件,被觸發時,彈出p元素的文本信息
$('p').on('click',function(){
alert( $(this).text() );
});
//在上面的基礎上,傳值給p元素
$('p').on('click',{foo:"bar"},function(event){
alert( event.data.foo );
});
二、on之事件代理
標准浏覽器中都有事件冒泡(bubble)或捕獲(propagate)機制(除IE)。
如下圖:

--當目標元素被觸發時,它的流程是,先從它祖先元素一層一層,跋山涉水將事件傳達給目標函數,如上圖中P的父元素 à target的父元素P à target,此為事件捕獲;
--當目標函數被觸發後,又將事件一層一層傳遞到根節點,即老祖宗,此為事件冒泡。
所有浏覽器都有事件冒泡機制。所以,我們可以利用這一特性,優化代碼,減少事件綁定。
on方法也利用了這一特性。當‘selector’被提供時,就是事件委托,事件觸發時,直接綁定在on方法上的元素是不會觸發該事件,而它指定的後代元素‘selector’就會利用冒泡機制,到直接綁定在on方法上的元素,給予處理。
舉個例子,我們在寫導航欄時,經常用到ul+li這種方式,當點擊每一個li時,頁面相應切換,沒有經驗的做法嘛,就是將每個li綁定一個click嘛。
那麼,問題來了。沒過幾天,突然我發現有幾個li的模塊其實可以整合到一起的,怎麼辦呢?刪除原來為li添加的事件,再重新寫過?
沒過幾天,假設有新需求來,我要加兩個模塊呢?
假如你用的是jQuery框架,完全可以在最開始用on方法嘛,利用事件委托其特性,一鍵搞定。
如下:
function doSomething(){
console.log(this);
}
$('ul').on('click','li',doSomething/*在這裡,doSomething方法中this指向的是li*/);
注:on方法中當selector有值時,雖然采用的冒泡機制,但this指向的是目標元素對象。
如:
function doSomething(event,name){
//結果為true
console.log( event.target === this );
}
$('ul').on('click','li',doSomething);
三、on之false
在on方法中,如果你想阻止事件冒泡又想阻止默認事件行為,你可以采用快捷方式,直接false。
如表單提交:
$('form').on('submit',false);
四、on之data
.on( events [,selector] [,data] ,handler)
當data有值且不為null或者undefined,事件被觸發時,它會被傳給event.data。
但,請注意,當你傳入data的值後,它是恆定不變的。什麼意思?
看看下面的demo:
<!DOCTYPE html>
<head>
<title>on</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<style>
ul{
overflow:hidden;
}
ul li{
float:left;
margin-left:10px;
list-style-type:none;
}
</style>
</head>
<body>
<ul>
<li>item1</li>
<li>item2</li>
</ul>
<!--需要自行引入jquery-->
<script src="jquery-1.12.0.js"></script>
<script>
var name = 'monkey';
/*5秒後將name的值變成'dorie'*/
setTimeout(function(){
name = 'dorie';
console.log('after setTimeout: ' + name);
},5000);
//打印event.data.msg
function doSomething(event){
console.log(event.data.msg);
};
//msg:name,即msg:'monkey'
$('ul').on('click','li',{msg:name},doSomething);
</script>
</body>
</html>
運行代碼後的結果:

我們不但可以這樣在綁定元素事件的時候賦予data值,我們還可以用.trigger()或者.triggerHandler()來傳遞值哦,只需要在觸發方法(如下的doSomething)中再加入一個參數哈。
如下:
/*第一個參數當然是用來接收event的哈*/
function doSomething(event,name){
console.log(name);
}
$('ul').on('click','li',doSomething);
/*here trigger*/
$('li').trigger('click','monkey');
那如果我想利用trigger傳入兩個或者多個值呢?是不是再加入幾個參數呢?
不太對,我們先看看下面的代碼:
<!DOCTYPE html>
<head>
<title>on</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<style>
ul{
overflow:hidden;
}
ul li{
float:left;
margin-left:10px;
list-style-type:none;
}
</style>
</head>
<body>
<ul>
<li>item1</li>
</ul>
<script src="jquery-1.12.0.js"></script>
<script>
/*傳入兩個參數name、age*/
function doSomething(event,name,age){
console.log(name);
console.log(age);
}
$('ul').on('click','li',doSomething);
$('li').trigger('click','monkey',100);
</script>
</body>
</html>
運行代碼結果如下:

so,那怎麼辦呢?
有兩個方法,可以達到你的目的。
方法一,參數不變,trigger傳入值時,傳入一個數組,數組中的值與參數一一對應就好了。
function doSomething(event,name,age){
console.log(name);
console.log(age);
}
$('ul').on('click','li',doSomething);
//trigger傳入對應數組
$('li').trigger('click',['monkey',100]);
方法二,參數和trigger傳入方式皆改變。都傳入對象嘛,不就只需要一個參數了麼。
function doSomething(event,obj){
console.log(obj.name);
console.log(obj.age);
}
$('ul').on('click','li',doSomething);
$('li').trigger('click',{name:'monkey',age:100});
五、其他
‘hover’在jQuery1.9中被移除了(注意是’hover’,而不是.hover()),所以on方法是無法調用hover的,
如下:

那如果我想利用on方法來實現hover的‘事件代理’呢?
怎麼辦呢?‘hover’都不存在了!!!
其實它一直都不在,只是’mouseenter’和’mouseleave’的快照(shorthand)而已。
所以,我們可以利用event.type來處理。
如下:
$('ul').on('mouseenter mouseleave','li',function(event){
if( event.type == 'mouseenter' ){
//相應處理
}
else if(event.type == 'mouseleave'){
//相應處理
}
});
另外,當我利用on為同一個事件,綁定了多個執行方法時,它會依次執行,如下:
<!DOCTYPE html>
<head>
<title>on</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<style>
ul{
overflow:hidden;
}
ul li{
float:left;
margin-left:10px;
list-style-type:none;
}
</style>
</head>
<body>
<ul>
<li>item1</li>
</ul>
<script src="jquery-1.12.0.js"></script>
<script>
$('li').on('click',function(){
console.log('1');
});
$('li').on('click',function(event){
console.log('2');
});
$('li').on('click',function(){
console.log('3');
});
</script>
</body>
</html>
運行後的結果:

倘若,我只想執行1、2,但是不想執行第三個click,輸出‘3’呢?
我們可以利用event.stopImmediatePropagation()
作用:阻止剩余的事件處理函數的執行,並阻止當前事件冒泡。
$('li').on('click',function(){
console.log('1');
});
$('li').on('click',function(event){
console.log('2');
event.stopImmediatePropagation();
});
$('li').on('click',function(){
console.log('3');
});
在上面大家也看見了,用on為同一個元素添加同一個事件時,事件是不會被覆蓋掉的,所以,為了避免代碼干擾,我們可以這樣綁定事件:
$('li').off('click').on('click',doSomething);
我們利用.off()還可以取消掉指定函數名的事件哦,而不是同一事件一切清空,前提是我們使用的是函數名。
如下:

像上面那樣,我們就可以清除方法名為one的click事件。
由於$(obj).click(dosomething)是$(obj).on(‘click’,dosomething)的快照(shorthand),所以.()off同樣適用於它.click()。
好了,時間也不早了。晚安,everyone~