zoukankan      html  css  js  c++  java
  • 测试DOM0级事件和DOM2级事件的堆叠

    1. 问题

    如果大家看过北风网CJ讲师的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 () { ...} 来添加事件。

    一直以来没有发现什么问题,直到给别人使用时,发现IE6~8通过该封装函数 addEvent 添加的 load 事件并没有执行,调试代码发现别人在 JS 中通过 window.onload 赋了一个处理函数,顿时明白这种 addEvent 封装的一个大Bug,原因很简单,通过DOM0级提供的事件接口多次添加时,后面的函数会覆盖前面的,而这种 addEvent 本质上就是一个 DOM0级函数,所以肯定会被后面的覆盖。

    也就是说, 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
    ';
    22         //     });
    23         // } else {
    24         //     btn.attachEvent('onclick', function () {
    25         //         output.value += 'DOM 2 Level Click
    ';
    26         //     })
    27         // }
    28 
    29         // 使用封装的 addEvent 函数
    30         // addEvent(btn, 'click', function () {
    31         //     output.value += 'DOM 2 Level Click
    ';
    32         // });
    33 
    34         btn.onclick = function () {
    35             output.value += 'DOM 0 Level Click 111111
    ';
    36         }
    37 
    38         btn.onclick = function () {
    39             output.value += 'DOM 0 Level Click 222222
    ';
    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 添加的事件处理函数。

    测试3: 将 DOM2 级事件保持注释状态,反注释掉 addEvent 部分, 可以看到只会输出 DOM 0 Level Click 22222。

    测试4: 在测试3 的基础上, 注释掉后面两个 DOM0 级添加事件的代码,以测试 addEvent 的输出,可以看到它输出 DOM 2 Level Click, 从而证明测试3中其被覆盖的结论。

    3. 总结

      1) DOM0 级事件和 DOM2 级事件可以共存;

      2) 尽量不要写 DOM0 级事件,特别是代码提供给别人使用时,绝对不能写!

  • 相关阅读:
    Windows Azure: Service Bus Queues 入门
    HTTP权威指南读书
    学习OpenWebkitSharp
    Intro to ASP.NET MVC 4 with Visual Studio [译五:添加一个模型]
    正则表达式
    运行page页面时的事件执行顺序
    C#cookie自动获取工具发布
    (译) Facebook工程师2012年小创意合集
    三层+临时表存储过程+巧用json+贱招图片加载+无刷新分页
    iOS开发那些事编写OCUnit测试方法应用测试方法
  • 原文地址:https://www.cnblogs.com/zhenyu-whu/p/3276763.html
Copyright © 2011-2022 走看看