由于事件处理程序可以为现代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. 用Quick Cocos2dx做一个连连看(三)

    做个日记吧. 最近比较忙,斗志也不高,昨天有点时间了,开始做了一下连接方法,一开始用的搜索算法,但是bug比较多,究其原因是对语法和算法都不是很熟悉. 然后昨天下午利用点时间用稍微通俗一点的连接算法, ...

  2. Python正则表达式学习笔记

    [] 字符类,只要匹配里面的任意字符,都算匹配 . 元字符,可以匹配除换行符之外的所有字符 大小写敏感,但是可以关闭 \d  可以匹配0-9中的任意数字 {3}大括号里面的数字,边上前面一个字符匹配的 ...

  3. OpenStack - liberty CentOS 7

    OpenStack私有云部署 Controller Node:       em1(10.6.17.11),em2() Computer Node:         em1(10.6.17.12),e ...

  4. (简单) POJ 2352 Stars,Treap。

    Description Astronomers often examine star maps where stars are represented by points on a plane and ...

  5. VI 摘要

    1  行首添加注释 1  :5,10s/^/#/g 2  sed '5,10s/^/#/' 2 替换某一个行 文本为 11111 22222 33333 替换: %s/\(.*\)/http:\/\/ ...

  6. bzoj-3450 Easy概率DP 【数学期望】

    Description 某一天WJMZBMR在打osu~~~但是他太弱逼了,有些地方完全靠运气:(我们来简化一下这个游戏的规则有n次点击要做,成功了就是o,失败了就是x,分数是按comb计算的,连续a ...

  7. 简单介绍java Enumeration

    Enumeration接口 Enumeration接口本身不是一个数据结构.但是,对其他数据结构非常重要. Enumeration接口定义了从一个数据结构得到连续数据的手段.例如,Enumeratio ...

  8. make的参数

    转载自 陈皓<跟我一起写 Makefile> 下面列举了所有GNU make 3.80版的参数定义.其它版本和产商的make大同小异,不过其它产商的make的具体参数还是请参考各自的产品文 ...

  9. SRM 592 DIV2 报告

    昨天下午查看邮箱,看到了topcoder的SRM比赛通知和cf的比赛通知,当时什么也不想做,心里空荡荡的,忽然就想参加一下,试试看.吃完晚饭回来一看,就剩十几分钟了,匆忙把平台下了,就开始等待比赛开始 ...

  10. easyui 翻译

    1,DataGrid checkOnSelect: 设置成true:用户点击一行的时候,复选框被选中或者是取消选中 设置成false:只有当用户点击复选框的时候,复选框才能被选中或者是取消选中 sel ...