zoukankan      html  css  js  c++  java
  • jquery event addEvent 分析

    1. Jquery提供了一些来进行regist,remove,fire事件的方法。   
    2. 6.2.1 Register   
    3. 对于注册事件,jquery提供了bind、one、toggle、hover四种注册事件的方法, bind是最基本的方法。One是注册只运行一次的方法,toggle注册交替运行的方法。Hover是注册鼠标浮过的方法。   
    4. bind : function(type, data, fn) {   
    5.     return type == "unload" ? this.one(type, data, fn) : this  
    6.         .each(function() {// fn || data, fn && data实现了data参数可有可无   
    7.                     jQuery.event.add(this, type, fn || data, fn && data);   
    8.                 }); },   
    9. Bind中对于unload的事件,只能运行一次,其它的就采用默认的注册方式。   
    10. // 为每一个匹配元素的特定事件(像click)绑定一个一次性的事件处理函数。   
    11. // 在每个对象上,这个事件处理函数只会被执行一次。其他规则与bind()函数相同。   
    12. // 这个事件处理函数会接收到一个事件对象,可以通过它来阻止(浏览器)默认的行为。   
    13. // 如果既想取消默认的行为,又想阻止事件起泡,这个事件处理函数必须返回false。   
    14.     one : function(type, data, fn) {   
    15.       var one = jQuery.event.proxy(fn || data, function(event) {   
    16.             jQuery(this).unbind(event, one);   
    17.             return (fn || data).apply(this, arguments);/this->当前的元素   
    18.                 });   
    19.             return this.each(function() {   
    20.                 jQuery.event.add(this, type, one, fn && data);   
    21.             });   
    22.         },   
    23. One与bind基本上差不多,不同的在调用jQuery.event.add时,把注册的事件处理的函数做了一个小小的调整。One调用了jQuery.event.proxy进行了代理传入的事件处理函数。在事件触发调用这个代理的函数时,先把事件从cache中删除,再执行注册的事件函数。这里就是闭包的应用,通过闭包得到fn注册的事件函数的引用。   
    24. //一个模仿悬停事件(鼠标移动到一个对象上面及移出这个对象)的方法。   
    25. //这是一个自定义的方法,它为频繁使用的任务提供了一种“保持在其中”的状态。   
    26.  //当鼠标移动到一个匹配的元素上面时,会触发指定的第一个函数。当鼠标移出这个元素时,   
    27. /会触发指定的第二个函数。而且,会伴随着对鼠标是否仍然处在特定元素中的检测(例如,处在div中的图像),   
    28.   //如果是,则会继续保持“悬停”状态,而不触发移出事件(修正了使用mouseout事件的一个常见错误)。   
    29.         hover : function(fnOver, fnOut) {   
    30.             return this.bind('mouseenter', fnOver).bind('mouseleave', fnOut);   
    31.         },   
    32. Hover则是建立在bind的基础之上。   
    33. //每次点击后依次调用函数。   
    34. toggle : function(fn) {        
    35. var args = arguments, i = 1;   
    36. while (i < args.length)//每个函数分配GUID   
    37.         jQuery.event.proxy(fn, args[i++]);//修改后的还在args中   
    38. return this.click(jQuery.event.proxy(fn, function(event) {//分配GUID          this.lastToggle = (this.lastToggle || 0) % i;//上一个函数                event.preventDefault();//阻止缺省动作   
    39.         //执行参数中的第几个函数,apply可以采用array-like的参数   
    40.         return args[this.lastToggle++].apply(this,arguments)||false;   
    41.     }));   
    42.     },   
    43. Toggle中参数可以是多个fn。先把它们代码生成UUID。之后调用click的方法来注册再次进行代理的callback。这个函数在事件触发时运行,它先计算上一次是执行了参数中的那个函数。之后阻止缺省动作。之后找到下一个函数运行。   
    44. //为jquery对象增加常用的事件方法   
    45. jQuery.each(   
    46.     ("blur,focus,load,resize,scroll,unload,click,dblclick,"  
    47.     + "mousedown,mouseup,mousemove,mouseover,mouseout,change,select,"    
    48. "submit,keydown,keypress,keyup,error").split(","),    
    49. function(i, name) {jQuery.fn[name] = function(fn) {   
    50.                     return fn ? this.bind(name, fn) : this.trigger(name);   
    51.                 };});   
    52. Jquery增加了一个常用的事件处理方法,包含上面调用的click。这里可以看出这里还是调用bind进行注册。当然这里还可以通过程序实现去触发事件。   
    53.   
    54. 上面的众多方法都是注册事件,其最终都落在jQuery.event.add();来完成注册的功能。如果我们采用Dom0或DOM1的事件方法,我们会采用elem.onclick=function(){}来为元素的某一种事件来注册处理函数。这个最大的缺点就是每个一个事件只是一个处理函数。在dom1的方式中有改进,我们可以采用elem.addEventListener(type, handle, false)为元素的事件注册多个处理函数。   
    55. 这样的处理方式还不是很完美,如果我们只这个事件运行一次就有点麻烦了。我们要在事件的处理函数中最后进行elem.removeEventListener来取消事件的监听。这样做可能会有事务上的问题。如果第一个事件处理函数在没有取消事件监听之前,就再次触发了怎么办?   
    56. 还有采用浏览器的方式,它不支持自定义事件的注册和处理,还不能为多个事件注册同一个处理函数。   
    57. jQuery.event = {// add 事件到一个元素上。   
    58. add : function(elem, types, handler, data) {   
    59. if (elem.nodeType == 3 || elem.nodeType == 8return;// 空白节点或注释   
    60.     // IE不能传入window,先复制一下。   
    61. if (jQuery.browser.msie && elem.setInterval) elem = window;   
    62. // 为handler分配一个全局唯一的Id   
    63. if (!handler.guid)  handler.guid = this.guid++;   
    64. // 把data附到handler.data中   
    65. if (data != undefined) {                                             ①   
    66. var fn = handler;   
    67. handler =this.proxy(fn,function(){return fn.apply(this,arguments);});   
    68. handler.data = data;   
    69.     }   
    70. // 初始化元素的events。如果没有取到events中值,就初始化data: {}       ②   
    71. var events =jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),   
    72. // 如果没有取到handle中值,就初始化data: function() {....}         ③   
    73. handle = jQuery.data(elem, "handle")|| jQuery.data(elem, "handle",   
    74. function() {//处理一个触发器的第二个事件和当page已经unload之后调用一个事件。   
    75.         if (typeof jQuery != "undefined"&& !jQuery.event.triggered)   
    76.             return jQuery.event.handle.apply(//callee.elem=handle.elem   
    77.                    arguments.callee.elem, arguments);   
    78.             });   
    79. // 增加elem做为handle属性,防止IE由于没有本地Event而内存泄露。   
    80. handle.elem = elem;   
    81. // 处理采用空格分隔多个事件名,如jQuery(...).bind("mouseover mouseout", fn);   
    82. jQuery.each(types.split(/\s+/), function(index, type) {       ④   
    83.     // 命名空间的事件,一般不会用到。   
    84. var parts = type.split(".");type = parts[0];handler.type = parts[1];   
    85.     // 捆绑到本元素type事件的所有处理函数   
    86. var handlers = events[type];                                         ⑤   
    87. if (!handlers) {// 没有找到处理函数列表就初始化事件队列   
    88.         handlers = events[type] = {};   
    89.     // 如果type不是ready,或ready的setup执行返回false                 ⑥   
    90. if (!jQuery.event.special[type]|| jQuery.event.special[type].setup   
    91.         .call(elem, data) === false) {// 调用系统的事件函数来注册事件   
    92. if(elem.addEventListener)elem.addEventListener(type,handle,false);   
    93. else if (elem.attachEvent)elem.attachEvent("on" + type, handle);   
    94.            }   
    95. }   
    96. // 把处理器的id和handler形式属性对的形式保存在handlers列表中,   
    97. // 也存在events[type][handler.guid]中。   
    98. handlers[handler.guid] = handler;                                   ⑦   
    99. // 全局缓存这个事件的使用标识   
    100. jQuery.event.global[type] = true;   
    101. });   
    102.   
    103.     elem = null// 防止IE内存泄露。   
    104.     },   
    105.     guid : 1,   
    106.     global : {},   
    107. jQuery.event.add通过jQuery.data把事件相关的事件名和处理函数有机有序地组合起存放在jQuery.cache中与该元素对应的空间里。我们就一个例子分析一下add的过程中:假如我们招待下面jQuery(e1).bind("mouseover mouseout", fn0);jQuery(e1).bind("mouseover mouseout", fn1)的语句。   
    108. 在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的作用了。   
    109. 在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}}。   
    110. jQuery.event.add很重要的任务就是把注册的事件函数有序地存放起来。以便remove和fire事件的函数能找到。   
    111. //{elem_uuid_1:{events:{mouseover:{fn_uuid:fn1,fn_uuid1:fn2},   
    112.                 //mouseout:{fn_uuid:fn1,fn_uuid1:fn2}},handle:fn}}  
  • 相关阅读:
    VxWorks固件分析方法总结
    WebGoat系列实验Injection Flaws
    WebGoat系列实验Cross-Site Scripting (XSS)
    WebGoat系列实验Denial of Service & Insecure Communication
    WebGoat系列实验Buffer Overflows & Code Quality & Concurrency
    WebGoat系列实验Authentication Flaws
    WebGoat系列实验Access Control Flaws
    20155224 聂小益 《基于Arm实验箱的接口测试和应用》 课程设计报告
    实验补交的链接
    2017-2018-2 20155224『网络对抗技术』Exp4:恶意代码分析
  • 原文地址:https://www.cnblogs.com/rooney/p/1346469.html
Copyright © 2011-2022 走看看