<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      js便簽筆記(5)——Dean Edwards大牛的跨瀏覽器AddEvent()設計(不知道是不是jQuery事件系統的原型)

      1. 前言:

      在看Aaron的jquery源碼解讀時候,看到事件系統那塊,作者提到了Dean Edwards的添加事件的設計,于是就點進去看了看。首先讓我吃驚的是,代碼非常少,寥寥幾十行,非常簡單。于是我就仔細的看了看(如果代碼太多,可能就直接不看了)。

      這段代碼是Dean Edwards在2005年寫的了,那時候還沒有jquery。但是它的設計思路確實和jquery的事件系統有些相似,即便是在9年之后的今天。

      于是把這段代碼仔細研究,并在此跟大家分享以下。它將幫助你更好的理解jquery的事件系統。

      先把源碼粘上,:

       1 function addEvent(element, type, handler) {
       2     // assign each event handler a unique ID
       3     if (!handler.$$guid) handler.$$guid = addEvent.guid++;
       4     // create a hash table of event types for the element
       5     if (!element.events) element.events = {};
       6     // create a hash table of event handlers for each element/event pair
       7     var handlers = element.events[type];
       8     if (!handlers) {
       9         handlers = element.events[type] = {};
      10         // store the existing event handler (if there is one)
      11         if (element["on" + type]) {
      12             handlers[0] = element["on" + type];
      13         }
      14     }
      15     // store the event handler in the hash table
      16     handlers[handler.$$guid] = handler;
      17     // assign a global event handler to do all the work
      18     element["on" + type] = handleEvent;
      19 };
      20 // a counter used to create unique IDs
      21 addEvent.guid = 1;
      22 
      23 function removeEvent(element, type, handler) {
      24     // delete the event handler from the hash table
      25     if (element.events && element.events[type]) {
      26         delete element.events[type][handler.$$guid];
      27     }
      28 };
      29 
      30 function handleEvent(event) {
      31     // grab the event object (IE uses a global event object)
      32     event = event || window.event;
      33     // get a reference to the hash table of event handlers
      34     var handlers = this.events[event.type];
      35     // execute each event handler
      36     for (var i in handlers) {
      37         this.$$handleEvent = handlers[i];
      38         this.$$handleEvent(event);
      39     }
      40 };
      View Code

       

      2. 該設計的優點:

      Dean Edwards在文章中提到了該設計的幾個優點:

      it performs no object detection  不執行對象檢測,不理解何意。。

      it does not use the addeventListener/attachEvent methods  不使用addeventListener/attachEvent方法,因為這兩個方法分別由不同的瀏覽器支持,使用時候需要判斷。  但是,在Dean Edwards提供的下載代碼中,應用到了addeventListener。

      it keeps the correct scope (the this keyword)  保持正確的作用域,即this關鍵字

      it passes the event object correctly  正確的傳遞event對象

      it is entirely cross-browser (it will probably work on IE4 and NS4)  保證瀏覽器兼容性,甚至支持IE4和NetSape4(2005年)

      and from what I can tell it does not leak memory  不會出現內存泄漏

       

      3. 代碼解讀:

      3.1 事件添加方法addEvent():

       1         //事件添加方法
       2         function addEvent(element, type, handler) {
       3 
       4             // assign each event handler a unique ID
       5             // 為傳入的每個事件初始化一個唯一的id
       6             if (!handler.$$guid) handler.$$guid = addEvent.guid++;   //下文:addEvent.guid = 1;
       7 
       8             // create a hash table of event types for the element
       9             // 給element維護一個events屬性,初始化為一個空對象。  
      10             // element.events的結構類似于 { "click": {...}, "dbclick": {...}, "change": {...} }  
      11             // 即element.events是一個對象,其中每個事件類型又會對應一個對象
      12             if (!element.events) element.events = {};
      13 
      14             // create a hash table of event handlers for each element/event pair
      15             // 試圖取出element.events中當前事件類型type對應的對象,賦值給handlers
      16             var handlers = element.events[type];
      17             if (!handlers) {
      18                 handlers = element.events[type] = {};
      19                 //如果handlers是undefined,則初始化為空對象
      20 
      21 
      22                 // store the existing event handler (if there is one)
      23                 // 如果這個element已經有了一個方法,例如已經有了onclick方法
      24                 // 就把element的onclick方法賦值給handlers的0元素,此時handlers的結構就是:
      25                 // { 0: function(e){...} }
      26                 // 此時element.events的結構就是: { "click": { 0: function(e){...} },  /*省略其他事件類型*/ } 
      27                 if (element["on" + type]) {
      28                     handlers[0] = element["on" + type];
      29                 }
      30             }
      31             // store the event handler in the hash table
      32             // 把當前的事件handler存放到handlers中,handler.$$guid = addEvent.guid++; addEvent.guid = 1; 肯定是從1開始累加的
      33             // 因此,這是handlers的結構就是 { 0: function(e){...}, 1: function(){}, 2: function(){} 等等... }
      34             handlers[handler.$$guid] = handler;
      35 
      36             // assign a global event handler to do all the work
      37             // 下文定義了一個handleEvent(event)函數
      38             // 將這個函數,綁定到element的type事件上。  說明:在element進行click時,將會觸發handleEvent函數,handleEvent函數將會查找element.events,并調用相應的函數。可以把handleEvent稱為“主監聽函數”
      39             element["on" + type] = handleEvent;
      40         };
      41 
      42         // a counter used to create unique IDs
      43         addEvent.guid = 1;

      以上代碼都給出了詳細的注釋,應該能看明白了。重新梳理以下數據結構,經過addEvent()函數之后,當前的數據結構為:(假如type = 'click')

           element: {
                      onclick: handleEvent(event),   /*下文定義的函數*/
                      events: {
                          click:{
                              0: function(){...},    /*element已有的click事件*/
                              1: function(){...},
                              2: function(){...}
                              /*.......其他事件......*/
                          },
                          change:{
                              /*省略*/
                          },
                          dbclick:{
                              /*省略*/
                          }
                      }
              }

      這樣的設計,其實已經具備了jquery事件系統的雛形,包含了兩個最主要的特點:

      • element上的所有事件,將保存到element.events屬性中,不是直接綁定到element上;
      • handleEvent作為element所有事件的“主監聽函數”,有它統一管理element上的所有函數。

      接著往下看:

       

      3.2 主監聽函數handleEvent(event):

       1         //主監聽函數
       2         function handleEvent(event) {
       3             // grab the event object (IE uses a global event object)
       4             // 在IE中,event需要通過window.event獲取
       5             event = event || window.event;
       6 
       7             // get a reference to the hash table of event handlers
       8             // 根據事件類型在events中獲取事件集合(events的數據結構,參考addEvent方法的注釋)
       9             var handlers = this.events[event.type];
      10             // 注意!注意!  這里的this不是window,而是element對象,因為上文 element["on" + type] = handleEvent;
      11             // 所以在程序執行時,handleEvent已經作為了element的一個屬性,它的作用域是element,即this === element
      12 
      13             // execute each event handler
      14             // 循環執行handlers集合里的所有函數    另外,這里執行事件時傳遞的event,無論在什么瀏覽器下,都是正確的
      15             for (var i in handlers) {
      16                 this.$$handleEvent = handlers[i];
      17                 this.$$handleEvent(event);
      18 
      19                 //此處為何要把handlers[i]賦值給this.$$handleEvent,然后在執行呢?
      20                 //而不是直接執行handlers[i](event)?
      21                 //跟內存泄漏有關?
      22                 //我也沒看明白,大家自己思考的,知道的可以分享給大家。
      23             }
      24         };

      以上就是主監聽函數的實現過程,都做了注釋,也不叫好理解,有個問題,已經在代碼中有黃色背景標出來了,有了解的,也麻煩分享給大家。

      jquery的主監聽函數執行時候實現的比較復雜,但是思路上和這個是一樣的。

       

      3.3 移除函數事件:

      1        //移除函數事件
      2         function removeEvent(element, type, handler) {
      3             // delete the event handler from the hash table
      4             // 循環element.events[type],根據handler的唯一的id,進行delete
      5             if (element.events && element.events[type]) {
      6                 delete element.events[type][handler.$$guid];
      7             }
      8         };

      移除函數比較簡單,不多解釋。

       

      4. 總結

      這段代碼相對于jquery的事件系統,少了事件的代理,以及模擬的時間冒泡。不考慮代理,當然就簡單許多。

      但是它已經點出了jquery事件系統的原型,理解它,能幫助你更好的理解jquery事件系統。

       

      補充:司徒正美的新書《javascript框架設計》中專門有一節講解:11.4 Dean Edward的addEvent.js源碼分析 260頁

       

      posted @ 2014-04-11 20:53  王福朋  閱讀(4231)  評論(11)    收藏  舉報
      主站蜘蛛池模板: 亚洲黄日本午夜一区二区| 蜜臀av日韩精品一区二区| 成人网站网址导航| 久久综合香蕉国产蜜臀av| 无码AV中文字幕久久专区| 午夜国产精品福利一二| 人人妻人人澡人人爽| 国产成人午夜福利在线播放| 孕交videos小孕妇xx| 国产suv精品一区二区四| 日韩本精品一区二区三区| 国产中文字幕在线一区| 无码国产精品一区二区免费式芒果| 亚洲av高清一区二区三| 高清无码爆乳潮喷在线观看| 国产一区二区三区小说| 在线a亚洲老鸭窝天堂| 欧洲美熟女乱又伦免费视频| 国产成人精品无码免费看| 精品视频在线观看免费观看| 东京热一区二区三区在线| 亚洲蜜臀av乱码久久| 无码一区二区三区免费| 绝顶丰满少妇av无码| 国产精品爽爽爽一区二区| 亚洲欧美日本久久网站| 伊人色综合久久天天| 蜜桃无码一区二区三区| 18岁日韩内射颜射午夜久久成人| 人妻无码中文字幕| 东京热无码国产精品| 男女啪啪高潮激烈免费版| 精品国产熟女一区二区三区| 亚洲国产成人av在线观看| 色伦专区97中文字幕| 国产免费午夜福利在线观看| 熟妇的奶头又大又长奶水视频| 久久人人97超碰人人澡爱香蕉| 国产成人永久免费av在线| 蜜桃av无码免费看永久| 色欲综合久久中文字幕网|