• 技术文章 >web前端 >js教程

    JavaScript事件委托的详细介绍(附代码)

    不言不言2019-03-15 14:23:14转载895
    本篇文章给大家带来的内容是关于JavaScript事件委托的详细介绍(附代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

    事件委托(又名事件代理),就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。

    网上有关于事件委托的一个“取快递”例子,十分生动,这里我对它作一些修改和拓展,然后通过程序来说明事件委托的机制。

    某公司有三位员工,他们的快递收件地址为公司,每当有快递送达时,快递员拨打其电话进行通知,他们接到电话后去取件。

    员工ID员工名称联系方式
    A111111
    B222222
    C333333
    对应到页面,就是每个员工是一个标记:
    <ul id="前台工作人员">
        <li id="A">员工甲</li>
        <li id="B">员工乙</li>
        <li id="C">员工丙</li>
    </ul>

    每位员工接电话取快递的行为就是一个个事件,这里我们假设收取快递行为对应着onclick事件:

    A.onclik = function() {
        收取快递;
    };
    B.onclick = function() {
        收取快递;
    };
    C.onclick = function() {
        收取快递;
    };

    以上的实现,通常为通过循环遍历每一个员工,为其增加事件:

    /*程序1*/
    var aUl = document.getElemengtByID("前台工作人员");
    var aLi = aUl.getElemengtsByTagName("li");
    for (var i = 0; i < aLi.length; i++) {
        aLi[i].onclick = function() {
            收取快递;
        }
    }

    可以看到,为每个员工都设置一个事件,会产生冗余代码,占用内存,同时会进行多次DOM操作(与DOM节点进行交互),影响页面运行性能。

    “减少DOM操作是性能优化的主要思想之一”

    于是,我们理所当然地想到:为什么不能让前台工作人员帮我们签收快递呢?

    <ul id="前台工作人员">
        <li id="A">员工甲</li>
        <li id="B">员工乙</li>
        <li id="C">员工丙</li>
    </ul>
    
    /*程序2*/
    var tel = document.getElementById("前台工作人员");
    tel.onclick = function() {
        收取快递;
    }

    假设此时快递员打电话通知员工甲取件(onclick),但员工甲的DOM节点<li>并无对应事件(onclick),所以这个事件会“冒泡”到<li>的父元素<ul>,发现<ul>上有onclick处理事件,于是触发该事件,由前台工作人员收取快递。

    可以看到,这样一来,不仅缩减代码量,同时与DOM节点的交互次数也得到了缩减。

    还有一个优点:当增加新的DOM节点时,自动携带父元素的事件效果。也就是说,当有一个新员工丁来公司后,前台工作人员会直接帮他收取快递,而无需专门为他设置事件。

    例如,当新员工丁来到公司后:

    ...
    <input type="button" id="btn" value="添加新员工">
    ...
    
    ...
    /*程序3*/
    var aBtn = document.getElementById("btn");
    aBtn.onclick = function() {
        var aLi = document.createElement("li");
        oLi.innerHTML = "员工丁";
        aUl.appendChild(aLi);
    }
    ...

    在不使用事件委托的程序中,新增的员工丁是没有事件的,我们需要用一个函数包含住程序1:

    /*程序4*/
    function pro1() {
        var aUl = document.getElemengtByID("前台工作人员");
        var aLi = aUl.getElemengtsByTagName("li");
        for (var i = 0; i < aLi.length; i++) {
            aLi[i].onclick = function() {
                收取快递;
            }
        }
    }

    然后在新增新员工丁的程序的末尾执行这个函数:

    /*程序5*/
    var aBtn = document.getElementById("btn");
    aBtn.onclick = function() {
        ...
        pro1();
    }

    这样做的缺点是显而易见的:DOM节点交互次数成倍增加。
    若我们采用事件委托机制来实现,就不会存在这个问题,子元素节点的onclick事件会直接在父元素节点得到执行。

    到这里,我们会想到:对于同一种事件来说,使用事件委托将其放置在父元素节点上固然很方便。但如果对于不同的子元素节点要执行不同的事件呢,还能使用事件委托吗?

    答案是肯定的。

    例如上述三位公司员工,总是使用固定品牌的快递:

    他们三位在接到电话后,前台工作人员需要去不同的地方取件,对于不使用事件委托的程序,需要对每个人设置独特的处理事件:

    var A = document.getElementById("A");
    var B = document.getElementById("B");
    var C = document.getElementById("C");
    
    A.onclick = function() {
        去园区大门取快递;
    }
    B.onclick = function() {
        去楼下取快递;
    }
    C.onclick = function() {
        去本层大厅取快递;
    }

    至少需要三次DOM操作,而且为每一个对应节点都设置了事件函数。

    而若采用事件委托:

    var aUl = document.getElemengtByID("前台工作人员");
    aUl.onclick = function (ev) {
        var target = ev || window.event; /*兼容浏览器*/
        var target = ev.target || ev.srcElement; /*兼容浏览器*/
        if (target.nodeName.toLocaleLowerCase() == "li") {
            switch(target.id) {
                case "A" :
                    去园区大门取快递;
                    break;
                case "B" :
                    去楼下取快递;
                    break;
                case "C" :
                    去本层大厅取快递;
                    break;
            }
        }
    }

    这样一来,DOM操作就只有一次,其他的操作都在JS内进行,可以有效提升网页性能。

    以上便是JS事件委托的基本思想。简而言之,就是利用事件冒泡这一特点,来对事件进行管理,减少冗余代码,减少不必要的创建,减少交互操作以节约内存和提高性能。

    事件冒泡

    事件冒泡是当触发某个DOM元素节点时,若该节点没有对应事件,则检查其父元素是否有对应事件,若有,则执行,若没有,继续向上检查。与其对应的还有事件捕获

    以上就是JavaScript事件委托的详细介绍(附代码)的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:segmentfault,如有侵犯,请联系admin@php.cn删除
    上一篇:资源合并与压缩的优化方法介绍 下一篇:JavaScript作用域和作用域链的解析(附示例)
    大前端线上培训班

    相关文章推荐

    • javascript变量提升的详细介绍(代码示例)• JavaScript如何获取字符串中出现多次的字符(代码)• JavaScript对象序列化、toString()与valueOf()的用法介绍• JavaScript中Promise.all和Promise.race方法的介绍(附代码)

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网