zoukankan      html  css  js  c++  java
  • jQuery 原理的模拟代码 3 事件处理

    在 jQuery 中,实际注册的事件处理函数是一个匿名的闭包函数,这个函数最终都是通过调用 jQuery.event.handle 进行处理的。

    在对象的私有扩展对象上,专门增加了一个名为 events 的事件管理对象,在这个对象上每种事件分别对应一个同名的属性,这个属性的值是一个数组,针对这个事件的处理程序依次压入这个数组中,构成一个事件处理的列表。自定义的事件处理函数即被压入这个列表中。

    在事件触发的时候,通过注册的匿名函数来执行 jQuery.event.handle ,由于使用了闭包,所以在这个函数中的 this 就是事件源对象,通过这个事件源对象找到对象的私有扩展数据,然后在 events 中找到对应的事件处理程序列表,最后,依次执行。

      1 /// <reference path="jQuery-core.js" />
      2 // #2076
      3 
      4 // 用于生成事件处理函数的 id
      5 jQuery.guid = 1;
      6 
      7 // jQuery 的事件对象
      8 jQuery.event = {    // # 1555
      9 
     10     // 为对象增加事件
     11     // elem 增加事件的元素, type 事件的名称, handler 事件处理程序, data 事件相关的数据
     12     add: function (elem, type, handler, data) {
     13 
     14         var handleObjIn, handleObj;
     15 
     16         // 确认函数有一个唯一的 ID
     17         if (!handler.guid) {
     18             handler.guid = jQuery.guid++;
     19         }
     20 
     21         // 取得这个元素所对应的缓存数据对象
     22         var elemData = jQuery.data(elem);
     23 
     24         // 取得元素对应的缓存对象上的事件对象和所有事件共用的处理程序
     25         var events = elemData.events = elemData.events || {};
     26         var eventHandle = elemData.handle;
     27 
     28         // 是否已经有事件处理函数 handle 只有一个,都是使用 jQuery.event.handle
     29         // 通过使用闭包,使得这个函数引用当前的事件对象,参数。
     30         if (!eventHandle) {
     31             elemData.handle = eventHandle = function () {
     32                 return jQuery.event.handle.apply(eventHandle.elem, arguments);
     33             };
     34         }
     35                 
     36         // 使得闭包处理程序可以找到事件源对象
     37         eventHandle.elem = elem;
     38 
     39         // 
     40         handleObj = { handler: handler, data: data};
     41         handleObj.namespace = "";
     42 
     43 
     44         handleObj.type = type;
     45         handleObj.guid = handler.guid;
     46 
     47         // 每种事件可以有一系列的处理程序,数组形式
     48         var handlers = events[type],
     49         special = jQuery.event.special[type] || {};
     50 
     51         // Init the event handler queue
     52         if (!handlers) {
     53             handlers = events[type] = [];
     54 
     55             // Check for a special event handler
     56             // Only use addEventListener/attachEvent if the special
     57             // events handler returns false
     58             // 完成实际的事件注册
     59             // 实际的事件处理函数是 eventHandle
     60             if (!special.setup || special.setup.call(elem, data, namespaces, eventHandle) === false) {
     61                 // Bind the global event handler to the element
     62                 if (elem.addEventListener) {
     63                     elem.addEventListener(type, eventHandle, false);
     64 
     65                 } else if (elem.attachEvent) {
     66                     elem.attachEvent("on" + type, eventHandle);
     67                 }
     68             }
     69         }
     70 
     71         // 自定义的处理函数在一个堆栈中,以后 jQuery.event.handle 到这里找到实际的处理程序
     72         handlers.push(handleObj);
     73                
     74         // Nullify elem to prevent memory leaks in IE
     75         elem = null;
     76     },
     77 
     78     global: {},
     79 
     80     // 真正的事件处理函数, 
     81     // 由于是通过  return jQuery.event.handle.apply(eventHandle.elem, arguments) 调用的
     82     // 所以,此时的 this 就是事件源对象,event 是事件参数
     83     handle: function (event) {  // 1904
     84         var all, handlers, namespaces, namespace, events;
     85 
     86         event = window.event;
     87         event.currentTarget = this;
     88 
     89         // 在当前的事件对象上找到事件处理列表
     90         var events = jQuery.data(this"events"), handlers = events[event.type];
     91 
     92         if (events && handlers) {
     93             // Clone the handlers to prevent manipulation
     94             handlers = handlers.slice(0);
     95 
     96             for (var j = 0, l = handlers.length; j < l; j++) {
     97                 var handleObj = handlers[j];
     98 
     99 
    100                 // 取得注册事件时保存的参数
    101                 event.handler = handleObj.handler;
    102                 event.data = handleObj.data;
    103                 event.handleObj = handleObj;
    104 
    105                 var ret = handleObj.handler.apply(this, arguments);
    106             }
    107         }
    108 
    109         return event.result;
    110     },
    111 
    112     // #2020
    113     special: {}
    114 
    115 }
    116 
    117 // bind 函数定义
    118 jQuery.fn.bind = function( type, fn)
    119 {
    120     var handler = fn;
    121 
    122     // 调用 jQuery.event.add 添加事件
    123     for (var i = 0, l = this.length; i < l; i++) {
    124             jQuery.event.add(this[i], type, handler);
    125         }
    126     return this;
    127 }
    128 
    129 jQuery.fn.unbind = function (type, fn) {
    130     // Handle object literals
    131     if (typeof type === "object" && !type.preventDefault) {
    132         for (var key in type) {
    133             this.unbind(key, type[key]);
    134         }
    135 
    136     } else {
    137         for (var i = 0, l = this.length; i < l; i++) {
    138             jQuery.event.remove(this[i], type, fn);
    139         }
    140     }
    141 
    142     return this;
    143 }
    144 // click 事件的注册方法
    145 jQuery.fn.click = function (fn) {
    146     this.bind("click", fn);
    147     return this;
    148 }

    这样,对于页面上的 id 为 msg 的元素,就可以通过下面的代码注册一个 click 事件处理函数。

    1 // 事件操作
    2 $("#msg").click(
    3     function () {
    4         alert(this.innerHTML);
    5     }
    6     );

     jQuery 原理的模拟代码 -0 目录

  • 相关阅读:
    归并排序
    边割集
    NBUT 1225 NEW RDSP MODE I 2010辽宁省赛
    NBUT 1218 You are my brother 2010辽宁省赛
    NBUT 1220 SPY 2010辽宁省赛
    NBUT 1219 Time 2010辽宁省赛
    NBUT 1223 Friends number 2010辽宁省赛
    NBUT 1217 Dinner 2010辽宁省赛
    第七届蓝桥杯个人赛省赛--C语言B组
    2017广东工业大学程序设计竞赛决赛 tmk买礼物
  • 原文地址:https://www.cnblogs.com/haogj/p/1789759.html
Copyright © 2011-2022 走看看