Ext2.2源码解析(一) -- Ext.util.Event

来源:互联网 发布:pro recorder同类软件 编辑:程序博客网 时间:2024/05/29 19:46
  1. (function(){
  2.    // 创建一个缓存性的监听器,当某个事件连续发生时,只有当时间停止一段事件,
  3.    // 事件响应函数才会触发
  4.     var createBuffered = function(h, o, scope){
  5.         var task = new Ext.util.DelayedTask();
  6.         return function(){
  7.             task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
  8.         };
  9.     };
  10.     // 创建触发一次的监听器
  11.     var createSingle = function(h, e, fn, scope){
  12.         return function(){
  13.             e.removeListener(fn, scope);
  14.             return h.apply(scope, arguments);
  15.         };
  16.     };
  17.     // 创建延时触发的事件监听器
  18.     var createDelayed = function(h, o, scope){
  19.         return function(){
  20.             var args = Array.prototype.slice.call(arguments, 0);
  21.             setTimeout(function(){
  22.                 h.apply(scope, args);
  23.             }, o.delay || 10);
  24.         };
  25.     };
  26.     // Ext封装的事件对象
  27.     Ext.util.Event = function(obj, name){
  28.         this.name = name;     // 事件的名称
  29.         this.obj = obj;       // 事件发生的对象
  30.         this.listeners = [];  // 事件的监听器
  31.     };
  32.     Ext.util.Event.prototype = {
  33.           /*
  34.            * 给当前事件增加一个事件监听器
  35.            *
  36.            * 参数:
  37.            *      fn      - 事件响应函数
  38.            *      scope   - 事件的作用域
  39.            *      options - 事件监听器的属性 如是否延时响应等
  40.            */
  41.         addListener : function(fn, scope, options){
  42.               // 将事件响应函数的作用域设置为指定的作用域或事件发生的对象
  43.             scope = scope || this.obj;
  44.             
  45.             // 如果scope作用域下的fn响应函数还没有注册,则注册,否则不重复注册
  46.             if(!this.isListening(fn, scope)){
  47.                   //  创建事件监听器
  48.                 var l = this.createListener(fn, scope, options);
  49.                 
  50.                 // 判断事件是否已经触发
  51.                 if(!this.firing){
  52.                       // 如果事件还没有触发,则将事件加入到监听器列表中
  53.                     this.listeners.push(l);
  54.                 }else
  55.                       // 如果事件已经触发,不打扰已注册监听器的执行,
  56.                       // 重新将监听器列表复制一份,监听器列表指向复制后的副本
  57.                     this.listeners = this.listeners.slice(0);
  58.                     // 将当前监听器增加到监听器列表中
  59.                     this.listeners.push(l);
  60.                 }
  61.             }
  62.         },
  63.         /*
  64.            * 创建一个监听器对象
  65.            *
  66.            * 参数:
  67.            *      fn      - 事件响应函数
  68.            *      scope   - 事件的作用域
  69.            *      options - 事件监听器的属性 如是否延时响应等
  70.            */
  71.         createListener : function(fn, scope, o){
  72.             o = o || {};
  73.             
  74.             // 将事件响应函数的作用域设置为指定的作用域或事件发生的对象
  75.             scope = scope || this.obj;
  76.             
  77.             // 创建事件监听器对象
  78.             var l = {fn: fn, scope: scope, options: o};
  79.             
  80.             var h = fn;
  81.             if(o.delay){
  82.                   // 创建延时触发的事件监听器
  83.                 h = createDelayed(h, o, scope);
  84.             }
  85.             if(o.single){
  86.                   // 创建触发一次的监听器
  87.                 h = createSingle(h, this, fn, scope);
  88.             }
  89.             if(o.buffer){
  90.                   // 创建一个缓存性的监听器,当某个事件连续发生时,只有当时间停止一段事件,
  91.                   // 事件响应函数才会触发
  92.                 h = createBuffered(h, o, scope);
  93.             }
  94.             l.fireFn = h;
  95.             return l;
  96.         },
  97.         /*
  98.            * 在监听器列表中查找指定作用域下的事件响应函数
  99.            *
  100.            * 参数:
  101.            *      fn      - 事件响应函数
  102.            *      scope   - 事件的作用域
  103.            * 
  104.            * 返回值:如果已经注册,返回该响应函数在监听器中的索引,否则返回-1
  105.            */
  106.         findListener : function(fn, scope){
  107.             scope = scope || this.obj;
  108.             var ls = this.listeners;
  109.             for(var i = 0, len = ls.length; i < len; i++){
  110.                 var l = ls[i];
  111.                 if(l.fn == fn && l.scope == scope){
  112.                     return i;
  113.                 }
  114.             }
  115.             return -1;
  116.         },
  117.         /*
  118.            * 判断指定作用域下的事件响应函数是否已注册
  119.            *
  120.            * 参数:
  121.            *      fn      - 事件响应函数
  122.            *      scope   - 事件的作用域
  123.            */
  124.         isListening : function(fn, scope){
  125.             return this.findListener(fn, scope) != -1;
  126.         },
  127.         /*
  128.            * 删除指定作用域下的事件响应函数
  129.            *
  130.            * 参数:
  131.            *      fn      - 事件响应函数
  132.            *      scope   - 事件的作用域
  133.            */
  134.         removeListener : function(fn, scope){
  135.             var index;
  136.             if((index = this.findListener(fn, scope)) != -1){
  137.                   // 如果事件还没有触发,则直接删除监听器
  138.                 if(!this.firing){
  139.                     this.listeners.splice(index, 1);
  140.                 }else{
  141.                       // 如果事件已经触发,不打扰已注册监听器的执行,
  142.                       // 重新将监听器列表复制一份,监听器列表指向复制后的副本
  143.                     this.listeners = this.listeners.slice(0);
  144.                     // 在新的监听器列表中删除该监听器
  145.                     this.listeners.splice(index, 1);
  146.                 }
  147.                 return true;
  148.             }
  149.             return false;
  150.         },
  151.         /* 
  152.          * 删除该事件的监听器列表
  153.            */
  154.         clearListeners : function(){
  155.             this.listeners = [];
  156.         },
  157.         /* 
  158.          * 事件触发,执行各个监听器中的响应函数
  159.            */
  160.         fire : function(){
  161.             var ls = this.listeners, scope, len = ls.length;
  162.             if(len > 0){
  163.                   // 修改事件触发标志位为“已触发”
  164.                 this.firing = true;
  165.                 var args = Array.prototype.slice.call(arguments, 0);
  166.                 for(var i = 0; i < len; i++){
  167.                     var l = ls[i]; 
  168.                     // 调用事件监听器中的事件响应函数
  169.                     if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
  170.                           // 如果监听器链中有一个事件响应函数返回false,则不触发后面的监听器
  171.                         this.firing = false;
  172.                         return false;
  173.                     }
  174.                 }
  175.                 // 修改事件触发标志位为“未触发”
  176.                 this.firing = false;
  177.             }
  178.             return true;
  179.         }
  180.     };
  181. })();
 
原创粉丝点击