jQuery源码分析之on方法

来源:互联网 发布:写关于宿舍知乎 编辑:程序博客网 时间:2024/05/21 00:00

测试代码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++,所以是2function 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 infojQuery().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类型,见代码1if ( 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 infojQuery().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方法传入的新的函数句柄,该新的函数通过闭包的形式访问原始的函数!

0 0