以下見解基於jquery v1.12.4
jquery的on() 方法在被選元素及子元素上新增一個或多個事件處理程式
$(selector).on(event,childSelector,data,function)
一直比較好奇jquery是怎麼處理多個引數可以只傳幾個,且順序不強制的,遂琢磨了下jquery的on方法
1、 dom結構
<div id="div1">
<p id="p1" class="p-text">文字1</p>
<p id="p2" class="p-text">文字2</p>
</div>
複製程式碼
2、 基本用法
2.1、 最簡單的用法
// 點選#div1列印 *點選了*
$('#div1').on('click', function (e) {
console.log('點選了')
})
複製程式碼
2.2、 事件委託
// 點選任意p標籤列印 *點選了*
$('#div1').on('click', 'p', function (e) {
console.log('點選了')
})
複製程式碼
2.3、 引數齊全的事件繫結
// 列印出*123*
$('#div1').on('click', 123, function (e) {
console.log(e.data)
})
// 點選不會發生任何事情
$('#div1').on('click', '123', function (e) {
console.log(e.data)
})
複製程式碼
問題來了,在事件委託那裡,我傳入的第2個元素是字串'p',在這裡傳入字串'123'點選毫無反應,傳入數字123則可以觸發。對比on方法的引數順序,可以發現以上三種例子的順序都不對應 這就引出了我一開始的問題:jquery是怎麼處理多個引數可以只傳幾個,且順序不強制的
通過研究一波jquery原始碼發現,其實原理很簡單,就是對傳入的引數進行(型別、null、undefined)判斷 在jquery內部,會按on方法提供的(約定的)順序對傳入的引數進行判斷並轉換成其需要的順序
擷取部分程式碼:
if ( data == null && fn == null ) {
// ( types, fn )
fn = selector;
data = selector = undefined;
} else if ( fn == null ) {
if ( typeof selector === "string" ) {
// ( types, selector, fn )
fn = data;
data = undefined;
} else {
// ( types, data, fn )
fn = data;
data = selector;
selector = undefined;
}
}
複製程式碼
原始碼位置:function on( elem, types, selector, data, fn, one )
3、 批量繫結事件
3.1、 批量繫結相同處理
// 點選、滑鼠移入列印*123*
$('#div1').on('click mouseenter', 123, function (e) {
console.log(e.data)
})
複製程式碼
3.2、 批量繫結不同處理
// 點選、滑鼠移入、移出列印對應訊息
$('#div1').on(
{
click: function (e) {console.log('點選:' + e.data)},
mouseenter: function (e) {console.log('滑鼠進入:' + e.data)},
mouseleave: function (e) {console.log('滑鼠移出!')}
},
123
)
複製程式碼
批量繫結不同處理,傳入物件形式的引數,內部對引數進行了for...in解構,處理位置:
...
for ( type in types ) {
on( elem, type, selector, data, types[ type ], one );
}
...
複製程式碼
兩種批量繫結事件最終都從on進入**add: function( elem, types, handler, data, selector ) **,在add方法進行最終的事件新增。 兩者最終都會經過add方法的如下程式碼處理:
...
// Handle multiple events separated by a space
types = ( types || "" ).match( rnotwhite ) || [ "" ]; // types被轉為陣列,進入while迴圈遍歷
t = types.length;
while ( t-- ) {
...
複製程式碼
4、 總結
雖然jquery內建了很多方便的處理,但還是有很多種情況考慮不到,比如下面這種情況就無法成功
$('#div1').on(['click', 'mouseenter'], function (e) {
console.log('點選了')
})
複製程式碼
所以,呼叫方法的時候還是按照約定好的資料結構來