由于事件处理程序可以为现代web应用提供交互能力,因此许多开发人员不分青红皂白向页面中添加大量的处理程序;这在某些语言中不会导致问题,但是在javascript,事件处理程序数量直接关系到页面的整体运行性能。因为,首先每个函数都是对象,都会占用内存,内存中对象越多,性能就越差;其次,必须事先指定所有事件处理程序而导致的dom访问次数,会延迟整个页面的交互就绪时间。

一、事件委托

  对“事件处理程序过多”问题的解决方案就是事件委托。事件委托利用了冒泡事件,只指定一个事件处理程序,就可以管理某一类型的所有事件。

<html>
    <head>
        <meta charset="utf-8">
        <title>事件委托</title>
    </head>
    <body>
        <ul id="myLinks">
            <li id="Gosomewhere">Go somewhere</li>
            <li id="dosomething">Do something</li>
            <li id="sayhi">Say hi</li>
        </ul>
    <script>
    // 跨浏览器的事件处理程序
        var EventUtil = {
            addHandler:function(element, type, handler){
                if(element.addEventListener){
                    // DOM2级事件
                    element.addEventListener(type, handler, false);
                }else if(element.attachEvent){
                    // IE事件
                    element.attachEvent(on+"type", handler);
                }else{
                    // DOM0级事件
                    element["on"+type] = handler;
                }
            },
            removeHandler:function(element, type, handler){
                if(element.removeEventListener){
                    // DOM2级事件
                    element.removeEventListener(type, handler, false);
                }else if(element.detachEvent){
                    // IE事件
                    element.detachEvent(on+"type", handler);
                }else{
                    // DOM0级事件
                    element["on"+type] = null;
                }
            },
            getEvent:function(event){
                return event? event:window.event;
            },
            getTarget:function(event){
                return event.target || event.srcElement;
            }
        };

        var list = document.getElementById("myLinks");

        EventUtil.addHandler(list, "click", function(event){
            event = EventUtil.getEvent(event);
            var target = EventUtil.getTarget(event);

            switch(target.id){
                case "dosomething":
                    document.title = "I changed the title."
                    break;
                case "Gosomewhere":
                    self.location.href = "http://www.baidu.com";
                    break;
                case "sayhi":
                    alert("hi");
                    break;
            }
        });
    </script>
    </body>
</html>

  这段代码只取得了一个DOM元素,只添加了一个事件处理程序,占用的内存也更少。最适合采用事件委托的事件包括:click, mousedown,mouseup,keydown,keyup和keypress。虽然mouseover和mouseout事件也冒泡,但要适当处理他们并不容易,而且需要经常计算元素的位置。


二、移除事件处理程序

  在不需要事件处理程序的时候把它们移除,能够提高页面的性能。内存中留有过时不用的“空事件处理程序”,也是造成web应用程序与性能问题的主要原因。在两种情况下,会造成上述原因:

1、从文档中移除带有事件处理的元素时,如果元素被innerHTML删除,那么原来添加到元素中的事件处理程序极有可能无法被当做垃圾回收;---------如果你知道某个元素即将被移除,最好手工移除事件处理程序;

2、如果在页面卸载之前没有清理干净事件处理程序,那么页面卸载后,它们就会滞留在内存中。每次页面来回切换或点击了刷新时,内存中滞留的事件数目就会增加,因此为事件处理程序的内存并没有被释放。--------最好的做法是在页面卸载之前,先通过onunload移除所有的事件处理程序。


三、模拟事件

  事件经常由用户操作或者通过其他浏览器功能来触发,也可以使用javascript在任意时刻触发特定的事件。在测试web应用程序时,模拟触发事件是一件及其有用的技术;DOM2规定了模拟事件的方式,IE也有自己模拟事件的方式,下面分别介绍:

1、在DOM中的事件模拟

  在DOM中,可以使用createEvent()创建event对象,这个方法接收一个参数,即表示的要创建的事件类型的字符串。这个字符串可以是以下几个之一:

  • UIEvents:一般化的UI事件
  • MouseEvents:一般化的鼠标事件
  • MutationsEvents:一般化的DOM变动事件
  • HTMLEvents:一般化的HTML事件

  在创建了event对象后,需要使用与事件有关的信息初始化,最后需要使用dispatchEvent()来触发事件。

1)模拟鼠标事件

        var btn = document.getElementById("myBtn");

        // 创建事件对象
        var event = document.createEvent("MouseEvents");

        // 初始化事件对象
        // 该函数接受15个参数,分别于鼠标事件的典型属性相对应,例如,是否按下了alt键等
        event.initMouseEvent("click", true, true, document.defaultView, 0, 0, 0, 0, 0,
            false, false, false, false, 0, null);

        // 触发事件
        btn.dispatchEvent(event);

2)键盘模拟事件

  由于DOM2级事件中,没有就键盘事件作出规定,因此只能使用DOM3级事件;在使用前,应该先检测浏览器是否支持DOM3级事件。

        // 以DOM3级别的方式创建事件对象
        if(document.implementation.hasFeature("keyboardEvents", "3.0")){
            var event = document.createEvent("keyboardEvents");
        }    

        // 初始化事件对象
        // 该函数接受一系列与键盘属性相关的参数
        event.initKeyboardEvent("keydown", true, true, document.defaultView, "a",0, "Shift", 0);

        // 触发事件
        textbox.dispatchEvent(event);

2、在IE中的事件模拟

  在IE中,可以通过document.createEventObject()创建event对象,然后手工为这个对象添加所有需要的信息,最后是调用fireEvent方法触发事件。

        var btn = document.getElementById("myBtn");

        //创建事件对象
        var event = document.createEventObject();

        // 初始化事件对象,模拟在一个按钮上触发click事件的过程
        event.screenX = 100;
        event.screenY = 0;
        event.clientX = 0;
        event.clientY = 0;
        event.ctrlKey = false;
        event.altKey = false;
        event.shiftKey = false;
        event.button =  0;

        // 触发事件
        btn.fireEvent("onclick", event);

《JAVASCRIPT高级程序设计》事件委托和模拟事件的更多相关文章

  1. 读书笔记(05) - 事件 - JavaScript高级程序设计

    HTML依托于JavaScript来实现用户与WEB网页之间的动态交互,接收用户操作并做出相应的反馈,而事件在此间则充当桥梁的重要角色. 日常开发中,经常会为某个元素绑定一个事件,编写相应的业务逻辑, ...

  2. JavaScript高级程序设计-13:事件

    JavaScript与HTML之间的交互是通过事件实现的. 一.事件流 首先我们要明白事件流的概念.当我们点击一个按钮时,也点击了按钮的容器元素,甚至也点击了整个事件.事件流描述就是从页面中接收事件的 ...

  3. javaScript事件机制深入学习(事件冒泡,事件捕获,事件绑定方式,移除事件方式,阻止浏览器默认行为,事件委托,模拟浏览器事件,自定义事件)

    前言 JavaScript与HTML之间的交互是通过事件实现的.事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间.可以使用侦听器(或处理程序)来预订事件,以便事件发生时执行相应的代码.这种在传统软 ...

  4. 《javascript高级程序设计》 touch事件的一个小错误

    最近一段时候都在拜读尼古拉斯大神的<javascript高级程序设计>,真的是一本好书,通俗易懂,条理比<javascript权威指南>好理解一些,当然<javascri ...

  5. JavaScript高级程序设计学习笔记--事件

    HTML事件处理程序 <input type="button" value="Click Me" onclick"showMessage()&q ...

  6. JavaScript高级程序设计笔记 事件冒泡和事件捕获

    1.事件冒泡 要理解事件冒泡,就得先知道事件流.事件流描述的是从页面接收事件的顺序,比如如下的代码: <body> <div> click me! </div> & ...

  7. javascript事件委托和jQuery事件绑定on、off 和one

    一. 事件委托什么是事件委托?用现实中的理解就是:有100 个学生同时在某天中午收到快递,但这100 个学生不可能同时站在学校门口等,那么都会委托门卫去收取,然后再逐个交给学生.而在jQuery 中, ...

  8. javascript 事件委托 和jQuery事件绑定on、off 和one

    一. 事件委托什么是事件委托?用现实中的理解就是:有100 个学生同时在某天中午收到快递,但这100 个学生不可能同时站在学校门口等,那么都会委托门卫去收取,然后再逐个交给学生.而在jQuery 中, ...

  9. javascript事件委托和jquery事件委托

    元旦过后,新年第一篇. 初衷:很多的面试都会涉及到事件委托,前前后后也看过好多博文,写的都很不错,写的各有千秋,自己思前想后,为了以后自己的查看,也同时为现在找工作的前端小伙伴提供一个看似更全方位的解 ...

随机推荐

  1. mysqldump导入导出mysql数据库

    body{ font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI& ...

  2. 中文字符 unicode转utf-8函数 python实现

    unicode编码范围 00000000-0000007F的字符,用单个字节来表示: 00000080-000007FF的字符用两个字节表示 (中文的编码范围) 00000800-0000FFFF的字 ...

  3. CentOS 6.4 x64 Percona-Server-5.6.15 源码安装

    首先下载 Percona-Server-5.6 http://www.percona.com/downloads/Percona-Server-5.6/LATEST/source/ 然后必须先安装cm ...

  4. 浅谈web应用的负载均衡、集群、高可用(HA)解决方案(转)

    1.熟悉几个组件 1.1.apache     —— 它是Apache软件基金会的一个开放源代码的跨平台的网页服务器,属于老牌的web服务器了,支持基于Ip或者域名的虚拟主机,支持代理服务器,支持安 ...

  5. mvn

    http://blog.csdn.net/z69183787/article/category/2265961

  6. 对float的理解

    从IE6下的双边距引出 对一个div设置float:left;同时设置了margin-left:100px时在IE6下会出现双边距. 有两种解决办法: 1,推荐办法.加display:inline 2 ...

  7. java调用C/C++写的dll(转)

    源:java调用C/C++写的dll Java语言本身具有跨平台性,如果通过Java调用DLL的技术方便易用,使用Java开发前台界面可以更快速,也能带来跨平台性. Java调用C/C++写好的DLL ...

  8. Java编译时出现No enclosing instance of type XXX is accessible.

    今天在编译Java程序的时候出现以下错误: No enclosing instance of type Main is accessible. Must qualify the allocation ...

  9. HDU 1813 Escape from Tetris

    TMDTMD IDA*没跑了.什么是IDA*? 就是迭代深搜+A*估个价. 然而为什么调了一天? n<=2的时候我输出了东西.... 看了一天. #include<iostream> ...

  10. java中的double

    代码如下: Double d1 = 0.35; Double d2 = 0.1; System.out.println(d1+d2); 结果很不幸不是0.45,而是0.4499999999999999 ...