天天看点

js中的事件代理/委托

在学习

事件代理

之前,我们首先要知道一个概念:

事件冒泡

事件冒泡

js中的事件代理/委托

事件捕获:

当某个元素触发某个事件(如onclick),顶层对象document就会发出一个事件流,随着DOM树的节点向目标元素节点流去,直到到达事件真正发生的目标元素。在这个过程中,事件相应的监听函数是不会被触发的。

事件目标:

当到达目标元素之后,执行目标元素该事件相应的处理函数。如果没有绑定监听函数,那就不执行。

事件冒泡:

从目标元素开始,往顶层元素传播。途中如果有节点绑定了相应的事件处理函数,这些函数都会被一次触发。

这是当一个事件触发时的三个阶段。

我们看一个例子:

<div onclick="d()">
        <ul id="myul">
            <li>1</li>
            <li>2</li>
            <li onclick="fun()">3</li>
        </ul>
</div>
    <!-- DOM树:html->body->div->ul->li -->
    <script>
        function d(){
            console.log("我是div");
        }
        function fun(){
            console.log("我是li");
        }
    </script>
           

当我们点击

li

时,首先从上到下进行事件捕获,然后执行函数,再事件冒泡,从当前元素逐级向上,如果有相同的事件就会触发。

js中的事件代理/委托

更好的理解为,html在页面中包含body、div、ul、li这些元素,body在页面中包含div、ul、li,div包含ul 、li ,li其实是位于ul的空间上,也位于div的空间上,如果li被点击,也就相当于ul div body html被点击,因为li就是在他们的空间上啊,所以有绑定事件的就会触发。

事件代理

事件代理

又叫事件委托,就是利用

事件冒泡的原理

,把本应该注册在子元素上的事件,注册在父元素上。点击子元素时,没有相应的注册事件,就会到父元素上寻找。

我相信大家学习这个的时候都见过这个例子:

有三个同事预计会在周一收到快递。为签收快递,有两种办法:一是三个人在公司门口等快递;二是委托给前台MM代为签收。现实当中,我们大都采用委托的方案(公司也不会容忍那么多员工站在门口就为了等快递)。前台MM收到快递后,她会判断收件人是谁,然后按照收件人的要求签收,甚至代为付款。这种方案还有一个优势,那就是即使公司里来了新员工(不管多少),前台MM也会在收到寄给新员工的快递后核实并代为签收。

事件代理的

好处

就是:

  • 当添加的事件太多的时候,需要不断的与

    dom

    节点进行交互,会延长整个页面的交互就绪时间。事件代理减少了

    dom

    操作,提高性能。
  • 新添加的子元素也会有相应的事件。

例子:

<body>
    <div>
        <table>
            <tr>
                <th>学号</th>
                <th>姓名</th>
                <th>性别</th>
                <th>年龄</th>
                <th>操作</th>
            </tr>
            <tr>
                <td>201211036</td>
                <td>小红</td>
                <td>女</td>
                <td>19</td>
                <td><input type="button" value="删除"></td>
            </tr>
            <tr>
                <td>201211089</td>
                <td>小屁</td>
                <td>男</td>
                <td>18</td>
                <td><input type="button" value="删除"></td>
            </tr>
            <tr>
                <td>201211143</td>
                <td>小绿</td>
                <td>女</td>
                <td>17</td>
                <td><input type="button" value="删除"></td>
            </tr>
        </table>
    </div>
</body>
           
js中的事件代理/委托

我们做一个这样的表格,实现各行的删除操作。如果按之前的事件来写,应该为每一行都添加一个事件。

<script>
        var tab=document.querySelector("table");//这个方法是返回文档中匹配css选择器的第一个元素
        tab.onclick=function(event){
            var tar=event.target;//event就是事件对象,包含了发生事件的各种信息,target保存了发生事件的节点
            //这种写法是为了浏览器的兼容
            if((tar)&&tar.nodeName.toLowerCase()==='input'){//点击删除按钮
                tar.parentNode.parentNode.parentNode.removeChild(tar.parentNode.parentNode);
            }
        }
        var row=tab.insertRow(tab.rows.length);
        var num=row.insertCell(0);
        num.innerHTML="201512036";
        var na=row.insertCell(1);
        na.innerHTML="小黄";
        var sex=row.insertCell(2);
        sex.innerHTML="男";
        var age=row.insertCell(3);
        age.innerHTML="20";
        var btn=row.insertCell(4);
        btn.innerHTML="<input type='button' value='删除' />";

        var ttr=document.createElement("tr");
        ttr.innerHTML="<td>20365897<\/td><td>小明<\/td><td>男<\/td><td>15<\/td><td><input type='button' value='删除' \/><\/td>";
        tab.appendChild(ttr);
        //使用原生js添加的方法
    </script>
           
js中的事件代理/委托

可以看到后面添加的行也可以删除,也有了相应的事件。

js