jQuery源码分析之Event事件分析(3)


jQuery.event = {// add 事件到一个元素上。
add : function(elem, types, handler, data) {
if (elem.nodeType == 3 || elem.nodeType == 8) return;// 空白节点或注释
  // IE不能传入window,先复制一下。
if (jQuery.browser.msie && elem.setInterval) elem = window;
// 为handler分配一个全局唯一的Id
if (!handler.guid)  handler.guid = this.guid++;
// 把data附到handler.data中
if (data != undefined) {                       ①
var fn = handler;
handler =this.proxy(fn,function(){return fn.apply(this,arguments);});
handler.data = data;
  }
// 初始化元素的events。如果没有取到events中值,就初始化data: {}    ②
var events =jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),
// 如果没有取到handle中值,就初始化data: function() {....}     ③
handle = jQuery.data(elem, "handle")|| jQuery.data(elem, "handle",
function() {//处理一个触发器的第二个事件和当page已经unload之后调用一个事件。
    if (typeof jQuery != "undefined"&& !jQuery.event.triggered)
      return jQuery.event.handle.apply(//callee.elem=handle.elem
          arguments.callee.elem, arguments);
      });
// 增加elem做为handle属性,防止IE由于没有本地Event而内存泄露。
handle.elem = elem;
// 处理采用空格分隔多个事件名,如jQuery(...).bind("mouseover mouseout", fn);
jQuery.each(types.split(/s+/), function(index, type) {    ④
  // 命名空间的事件,一般不会用到。
var parts = type.split(".");type = parts[0];handler.type = parts[1];
  // 捆绑到本元素type事件的所有处理函数
var handlers = events[type];                     ⑤
if (!handlers) {// 没有找到处理函数列表就初始化事件队列
    handlers = events[type] = {};
   // 如果type不是ready,或ready的setup执行返回false         ⑥
if (!jQuery.event.special[type]|| jQuery.event.special[type].setup
    .call(elem, data) === false) {// 调用系统的事件函数来注册事件
if(elem.addEventListener)elem.addEventListener(type,handle,false);
else if (elem.attachEvent)elem.attachEvent("on" + type, handle);
     }
}
// 把处理器的id和handler形式属性对的形式保存在handlers列表中,
// 也存在events[type][handler.guid]中。
handlers[handler.guid] = handler;                  ⑦
// 全局缓存这个事件的使用标识
jQuery.event.global[type] = true;
});
  
  elem = null; // 防止IE内存泄露。
  },
  guid : 1,
  global : {},



  jQuery.event.add通过jQuery.data把事件相关的事件名和处理函数有机有序地组合起存放在 jQuery.cache中与该元素对应的空间里。我们就一个例子分析一下add的过程中:假如我们招待下面 jQuery(e1).bind("mouseover mouseout", fn0);jQuery(e1).bind("mouseover mouseout", fn1)的语句。

  在jQuery(e1).bind("mouseover mouseout", fn0);时,②③都不可能从cache取到数,先初始化。此时的cache:{e1_uuid:{events:{},handle:fn}}。接着在 ⑤会为mouseover mouseout名初始化。此时的cache: {e1_uuid:{events:{ mouseover:{}, mouseout:{}},handle:fn}}。在⑥处向浏览器的事件中注册处理函数。接着⑦会把处理函数到事件名中。此时的cache: {e1_uuid:{events:{mouseover:{fn0_uuid:fn0},mouseout:{ fn0_uuid:fn0}},handle:fn}}。这里可以看出为采用proxy为函数生成uuid的作用了。

   在jQuery(e1).bind("mouseover mouseout", fn1)时,②③都从cache取到数据{e1_uuid:{events:{mouseover:{fn0_uuid:fn0},mouseout:{ fn0_uuid:fn0}},接着在⑤取到mouseover:{fn0_uuid:fn0},mouseout:{ fn0_uuid:fn0}的引用。接着⑦会把处理函数注册到事件名中。此时的cache: {e1_uuid:{events:{mouseover:{fn0_uuid:fn0, fn1_uuid:fn1,},mouseout:{ fn0_uuid:fn0, fn1_uuid:fn1}},handle:fn}}。

  jQuery.event.add很重要的任务 就是把注册的事件函数有序地存放起来。以便remove和fire事件的函数能找到。

//{elem_uuid_1:{events:{mouseover:{fn_uuid:fn1,fn_uuid1:fn2},
       //mouseout:{fn_uuid:fn1,fn_uuid1:fn2}},handle:fn}}

   6.2.2 trigger



  注册了事件,如onclick。那么当用户点击这个元素时,就会自动触发这个事件的已经注册的事件处理函数。但是我们有的时候要采用程 序来模拟事件的触发就得采用强迫触发某个事件。在IE中我们可以采用.fireEvent()来实现。如:<form onsubmit="a()" >中,如果button的form.submit()的方式提交表单,是不会主动触发onsumbit事件的,如果必须的话,就要在submit 前$(“:form”)[0].fireEvent("onsubmit”,),这样就会触发该事件。

  在mozilla中有三个步骤:   var  evt  =  document.createEvent('HTMLEvents');

   evt.initEvent('change',true,true);  t.dispatchEvent( evt );

  在 prototype是采用这样的方式来实现的。那么jquery中呢,它的实现方式有一点不一样。

复制代码 代码如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wdxxjp.html