由于事件处理程序可以为现代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. (中等) POJ 2948 Martian Mining,DP。

    Description The NASA Space Center, Houston, is less than 200 miles from San Antonio, Texas (the site ...

  2. (简单) POJ 3087 Shuffle'm Up,枚举。

    Description A common pastime for poker players at a poker table is to shuffle stacks of chips. Shuff ...

  3. 在mac本上删除mysql

    The steps: First you need to edit the file in: /etc/hostconfig and remove the line Since this is a s ...

  4. TCP/IP协议头部结构体(网摘小结)(转)

    源:TCP/IP协议头部结构体(网摘小结) TCP/IP协议头部结构体(转) 网络协议结构体定义 // i386 is little_endian. #ifndef LITTLE_ENDIAN #de ...

  5. Qt下libusb-win32的使用方法(转)

    源:Qt下libusb-win32的使用方法 之前一直找不到适合WIN7下的Tiny6410的USB下载软件,正好这几天开始学习USB,所以打算自己写一个专门用于Tiny6410的WIN7下的USB下 ...

  6. ajax 页面请求后,jsp页面定位

    如下图所示.A,B两区域为不动区域,既不随着滚动条的滚动而移动.C区域为异步加载内容区域, 在C区域中,点击查询按钮,需要异步加载查询 结果.但是查询结果会很长,这样子,就需要向下滑动滚动条,用户体验 ...

  7. mysql中游标的使用案例详解(学习笔记)

    1.游标是啥玩意?简单的说:游标(cursor)就是游动的标识,啥意思呢,通俗的这么说,一条sql取出对应n条结果资源的接口/句柄,就是游标,沿着游标可以一次取出一行.我给大家准备一张图: 2.怎么使 ...

  8. 网页代码DIV+CSS布局积累

    11.17 CSS英文命名在写CSS的时候,经常为一些名字而发愁,比如说菜单后面的背景要用什么词来表示呢?大家都知道,菜单一般用menu来表示,那么菜单后面的背景我会用menubg,CSS里就写#me ...

  9. 数值选择器(NumberPicker)的功能与用法

    数值选择器用于让用户输入数值,用户既可以通过键盘输入数值,也可以通过拖动来选择数值.使用该组件常用如下三个方法. setMinValue(int minVal):设置该组件支持的最小值. setMax ...

  10. TIMESTAMP和DATETIME哪个好

    日期范围 TIMESTAMP 支持从'1970-01-01 00:00:01′ 到 '2038-01-19 03:14:07′ UTC. 这个时间可能对目前正在工作的人来说没什么问题,可以坚持到我们退 ...