測試DOM0級事件和DOM2級事件的堆疊

1. 問題

若是你們看過北風網CJ講師的Javascript視頻教程,就能夠看到其封裝了一個很強的事件添加和刪除函數,以下所示javascript

 1  function addEvent(obj, evtype, fn) {
 2     //符合W3C的事件模型
 3     if (obj.addEventListener) {
 4         obj.addEventListener(evtype,fn,false);
 5         return obj;
 6     }
 7         
 8     //IE或Opera瀏覽器
 9     if (!obj.functions) obj.functions={};
10     if (!obj.functions[evtype])
11         obj.functions[evtype] = [];
12         
13     var functions=obj.functions[evtype];
14     for (var i=0;i<functions.length;i++) {
15         if (functions[i] === fn) return obj;
16     }
17     functions.push(fn);
18     
19     
20     if (typeof obj["on"+evtype]=="function") {
21         if (obj["on"+evtype]!=handler)
22             functions.push(obj["on"+evtype]);
23     }
24     obj["on"+evtype]=handler;
25     return obj;    
26 }
27 
28 
29  function delEvent(obj,evtype,fn) {
30     if (obj.removeEventListener) {
31         obj.removeEventListener(evtype,fn,false);
32         return obj;
33     }
34     var fns=obj.functions || {};
35     fns=fns[evtype] || [];
36     for (var i=0;i<fns.length;i++) {
37         if (fns[i]==fn) {
38             fns.splice(i,1);
39             return obj;
40         }
41     }
42 }

它由於各類緣由,沒有采用IE的DOM2級事件添加函數attachEvent,以期達到很是完美的兼容性,聽說能夠到 IE5.5 或如下。分析代碼頁能夠看到,它經過給DOM元素添加一個以 on + ‘type’ 爲名的屬性,其對應的值是一個處理函數的數組,本質來講就是僅僅利用 DOM0級提供的接口 elem.onclick = function () { ...} 來添加事件。html

一直以來沒有發現什麼問題,直到給別人使用時,發現IE6~8經過該封裝函數 addEvent 添加的 load 事件並無執行,調試代碼發現別人在 JS 中經過 window.onload 賦了一個處理函數,頓時明白這種 addEvent 封裝的一個大Bug,緣由很簡單,經過DOM0級提供的事件接口屢次添加時,後面的函數會覆蓋前面的,而這種 addEvent 本質上就是一個 DOM0級函數,因此確定會被後面的覆蓋。java

也就是說, addEvent 是假定網頁JS代碼中不使用 DOM0級添加事件。數組

 

2. 構建測試頁面和代碼

 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 2 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
 3 <head>
 4     <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
 5     <script src="dom.event.js"></script>
 6     <title>測試DOM0級事件和DOM2級事件的堆疊</title>
 7 </head>
 8 <body>
 9     <textarea name="have" id="output" cols="30" rows="10"></textarea>
10 
11     <button id="testBtn">測試</button>
12 
13     <script type="text/javascript">
14         var btn = document.getElementById('testBtn');
15         var output = document.getElementById('output');
16 
17 
18         // 標準的 DOM2 級事件添加方法
19         // if (btn.addEventListener) {
20         //     btn.addEventListener('click', function () {
21         //         output.value += 'DOM 2 Level Click\r\n';
22         //     });
23         // } else {
24         //     btn.attachEvent('onclick', function () {
25         //         output.value += 'DOM 2 Level Click\r\n';
26         //     })
27         // }
28 
29         // 使用封裝的 addEvent 函數
30         // addEvent(btn, 'click', function () {
31         //     output.value += 'DOM 2 Level Click\r\n';
32         // });
33 
34         btn.onclick = function () {
35             output.value += 'DOM 0 Level Click 111111\r\n';
36         }
37 
38         btn.onclick = function () {
39             output.value += 'DOM 0 Level Click 222222\r\n';
40         }
41 
42     </script>
43 </body>
44 </html>

測試1:點擊測試按鈕,能夠看到textarea 中只是輸出 DOM 0 Level Click 22222 信息,也就是後面添加的事件覆蓋了以前添加的,跟變量賦值是一個道理!!瀏覽器

測試2:將 DOM2 級事件添加的代碼反註釋掉,打開網頁點擊測試按鈕,能夠看到會輸出 DOM 2 Level Click 和 DOM 0 Level Click 22222,也就是說DOM0 級事件和 DOM2 級添加的事件都會處理,DOM0級並不會覆蓋 DOM2 添加的事件處理函數。dom

測試3: 將 DOM2 級事件保持註釋狀態,反註釋掉 addEvent 部分, 能夠看到只會輸出 DOM 0 Level Click 22222。函數

測試4: 在測試3 的基礎上, 註釋掉後面兩個 DOM0 級添加事件的代碼,以測試 addEvent 的輸出,能夠看到它輸出 DOM 2 Level Click, 從而證實測試3中其被覆蓋的結論。測試

 

3. 總結

  1) DOM0 級事件和 DOM2 級事件能夠共存;ui

  2) 儘可能不要寫 DOM0 級事件,特別是代碼提供給別人使用時,絕對不能寫!spa

相關文章
相關標籤/搜索