jQuery源码分析之on方法

测试代码1:

var data = { id: 5, name: "张三" };
var events = {
"mouseenter": function(event){
$(this).html( "你好," + event.data.name + "!");       
},
"mouseleave": function(event){
$(this).html( "再见!");
}       
};
//为n5绑定mouseenter mouseleave两个事件,并为其传入附加数据data
$("body").on(events, "#n5", data);
});
测试代码2:

  var eventsMap = {
"mouseenter": function(event){
$(this).html( "Hello!");        
},
"mouseleave": function(event){
$(this).html( "Bye!");
}
};
//为n5绑定mouseenter mouseleave两个事件
 $("#n5").one( eventsMap );
 alert(typeof eventsMap);//eventsMap是object
测试代码3:

$("div").on("click", "p", function(){
// 这里的this指向触发点击事件的p元素(Element)
alert( $(this).text() );
});
这种调用逻辑的时候:第一个参数是types,第二个参数是selector,第三个参数是fn
returnFalse函数:

function returnFalse() {
                 return false;
                   }
测试代码4:

<input id="btn" type="button" value="点击" />
$("#btn").bind("click", function(){
alert("我是前面已经绑定的事件!");
});
// 只有第一次点击时,执行该事件处理函数
// 执行后one()会立即移除绑定的事件处理函数
$("#btn").one("click", function(){
alert("只弹出一次提示框!");
});
测试代码5:

$(function()
{
alert(jQuery.guid);//打印1
$("input").bind("click",function()
{
  alert("点击!");
})
alert(jQuery.guid);//打印2
})
jQuery中为每一个函数设置一个全局的guid属性,该guid用于事件模块和缓存模块
测试uuid和guid:

<html>
<head>
<script type="text/javascript" src="/jquery/jquery.js"></script>
<script type="text/javascript">
$(function()
{
alert(jQuery.guid);//默认初始值是1

$("input").bind("click",function()
{
  alert("点击!");
})
alert(jQuery.guid);//事件处理或者缓存系统会把guid++,所以是2
function T()
{
 alert("我测试你在不");
}
$("input").bind("click",T)
alert(jQuery.guid);//再次绑定事件以后guid++变成3,所以全局jQuery.guid是不断自增的!
alert(T.guid);//但是对于这个T函数来说,他是第二个函数,所以他的guid只是2
//下面为button添加数据测试uuid
$("button").data("sex","male");
alert("data添加数据测试uuid->"+jQuery.uuid);//uuid默认是0,采取++index前增长策略
alert("data添加数据测试jQuery.expando->"+jQuery.expando);
alert("data添加数据测试id->"+$("input")[0][jQuery.expando]);//记住这里是DOM对象!
/*Query.data( elem, name, data, pvt)  
  elem[ internalKey ] = id = ++jQuery.uuid;  
jQuery.event.add: function( elem, types, handler, data, selector )  
  handler.guid = jQuery.guid++;
(每次绑定一个事件把事件处理函数的guid赋值,赋值为全局的guid的值。但是每次绑定guid自增,所以函数用到的只是前面的一个guid,这主要来源于guid++是赋值后增长的!所以T.guid===2不是3)
})
</script>
</head>
<body>
<p>段落文本内容
<input type="button" value="点击" />    
</p>
</body>
</html>
每次绑定事件都会把guid自增,每次存储数据会把uuid自增!
代码片段分析:‘

fn = function( event ) {
// Can use an empty set, since event contains the info
jQuery().off( event );
return origFn.apply( this, arguments );
};
对于fn来说,添加事件以后传入该函数一个[object MouseEvent]对象,他做的事情有两件:(1)把这个MouseEvent事件通过jQuery().off移除
(2)把上次的one函数传递进来的函数通过闭包引用并且执行!
  实例代码:(第一次点击弹出两个对话框,以后弹出一次!,因为click事件已经被移除了!)
  <input id="btn" type="button" value="点击" />
  $("#btn").bind("click", function(){
alert("我是前面已经绑定的事件!");
});
// 只有第一次点击时,执行该事件处理函数·1
// 执行后one()会立即移除绑定的事件处理函数
$("#btn").one("click", function(){
alert("只弹出一次提示框!");
});
下面开始on方法的源码分析:

on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
var type, origFn;
// Types can be a map of types/handlers
//如果第一个types的对象是object类型,见代码1
if ( typeof types === "object" ) {
// ( types-Object, selector, data )
//如果第二个参数不是string,那么调用方式就是$("p").on(typeObject,dataObject)也就是第一个参数是type对象,第二个参数是数据对象
if ( typeof selector !== "string" ) {
// ( types-Object, data )
data = data || selector;
selector = undefined;
}
//获取types封装的每一个type对象
for ( type in types ) {
//继续逐个绑定到选择器选择的对象上面去。也就是虽然事件类型是一个object对象,但是还是要逐个绑定事件
//type是"mouseenter",但是types[type]就是function对象
this.on( type, selector, data, types[ type ], one );
}
return this;
}
 //如果第一个参数不是object类型,同时第三个和第四个参数data和fn同时是null,因为undefined==null恒成立!
 //这个if语句的调用逻辑是:$("p").on("click",function(){})也就是只有两个参数,这种调用方式第二个参数是fn
 //第一个是types,data和selector是undefined。on: function( types, selector, data, fn, /*INTERNAL*/ one )
if ( data == null && fn == null ) {
// ( types, fn )
//把selector赋值给fn,记住韦恩图的逻辑!
fn = selector;
data = selector = undefined;
} else if ( fn == null ) {//仅仅fn为null,data不是null,function( types, selector, data, fn, /*INTERNAL*/ one )
if ( typeof selector === "string" ) {
// ( types, selector, fn )
fn = data;
data = undefined;
} else {
// ( types, data, fn )调用方式
//function( types, selector, data, fn, /*INTERNAL*/ one )
fn = data;
data = selector;
selector = undefined;
}
}
//如果第四个参数是false,那么就把事件触发时候的回调函数设为returnFalse函数!
if ( fn === false ) {
fn = returnFalse;
} else if ( !fn ) {
return this;
}
//如果传入了最后一个参数,同时设置为1,在下面的one()函数中会被调用
if ( one === 1 ) {
//保存原来的传递过来的事件函数
//把one调用的函数作为局部变量保存下来
origFn = fn;
//对传进来的fn重新赋值,这个函数是一个全新的函数,这个函数首先移除相应的事件,移除以后还要做一件事就是把one传递进来的函数执行
//一次
fn = function( event ) {
// Can use an empty set, since event contains the info
jQuery().off( event );
return origFn.apply( this, arguments );
};
// Use same guid so caller can remove using origFn
//设置新函数的guid,如果one传进来的函数已经有了guid,那么直接赋值,否则从jQuery获取
fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
}
//jQuery.event.add传入参数,第一个参数是遍历出来的jQuery对象转化成的DOM对象,即$("p")[i]
//第二个参数是类型,第三个参数回调函数,第四个参数是传递的额外数据,最后一个是选择器
return this.each( function() {
//把这个新函数添加到相应的this对象上去,this是jQuery对象
jQuery.event.add( this, types, fn, data, selector );
});
},
总结:

on方法其实就是对每一个调用对象单独调用jQuery.event.add方法进行事件绑定!但是因为one方法也是调用的是on方法,所以最后一个参数one就是表示是否是one方法,如果是,该方法就是首先把该事件移除,同时为add方法传入的新的函数句柄,该新的函数通过闭包的形式访问原始的函数!

你可能感兴趣的:(jQuery源码分析之on方法)