JavaScript学习--事件冒泡、事件捕获、事件代理

时间:2019-01-23
本文章向大家介绍JavaScript学习--事件冒泡、事件捕获、事件代理,主要包括JavaScript学习--事件冒泡、事件捕获、事件代理使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

学习《JavaScript高级程序设计(第3版)》

事件流

事件流描述的是从页面中接收事件的顺序。然而,但是当时的两大浏览器IE和Netscape团队的事件流分别是事件冒泡流和事件捕获流。

如果你点击了按钮,他们都认为点击事件不仅仅发生在按钮上。换句话说,点击了按钮的同时,你也点击了按钮的容器元素,甚至也点击了整个页面。

事件冒泡

IE的事件流叫做事件冒泡,即事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点。
例如:

<!DOCTYPE html>
<html>
    <head>
        <title>Event Bubbling Example</title>
    </head>
    <body>
        <div id="myDiv">Click me!</div>
    </body>
</html>

当你点击了页面中的<div>元素,那么这个click事件会按照如下的顺序传播:
(1)<div>
(2)<body>
(3)<html>
(4)document
即DOM事件沿DOM树向上传播。现代所有的浏览器都支持事件冒泡,但是IE5.5版本及之前的版本会跳过<html>元素。IE9、FireFox、Chrome和Safari则将事件一直冒泡到window。

事件捕获

事件捕获和事件冒泡的过程相反。即从不太具体的节点更早接收到事件,最具体的节点最慢收到事件。前面这个例子的顺序在事件传播中为:
(1)document
(2)<html>
(3)<body>
(4)<div>

事件捕获的用意在于事件到达预定目标之前捕获它。

虽然事件捕获是Netscape Communicator 唯一支持的事件流模型,但IE9、Safari、Chrome、Opera和FireFox目前都支持这种事件流模型。尽管DOM2级事件规范要求事件应该从document对象开始传播,但是这些浏览器都是从window对象开始捕获事件的。
建议使用事件冒泡,特殊需要时再使用事件捕获。

DOM2事件流

“DOM2级事件”规定事件流包括3个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。事件捕获为截获事件提供了机会,事件冒泡对事件作出响应。结果就是有两个机会在目标对象上面操作事件。

事件委托/事件代理

在JavaScript中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能。

  • 每个函数都是对象,都会占用内存;内存中的对象越多,性能就越差。
  • 必须事先指定所有事件处理程序而导致的DOM访问次数,会延迟整个页面的交互就绪事件。
  • 对“事件处理程序过多”的问题的解决方案就是事件委托

事件委托利用了事件冒泡,即指定一个事件处理程序,就可以管理某一类型的所有事件。
例如,由于click事件会一直冒泡到document层次,也就是说,我们可以为整个页面指定一个onclick事件处理程序,而不必给每个可单击的元素分别添加事件处理程序,只需要在DOM树中尽量最高的层次上添加一个事件处理程序。

例子如下:

<ul>
    <li id = "gosomewhere">go somewhere</li>
    <li id = "dosomething">do something</li>
    <li id="sayHi">say Hi</li>
</ul>
var list = document.getElementById("mylinks");

EventUtil.addhamdle(list,'click',function(event){
	// 获取这个事件
    event = EventUtil.getEvent(event);
    // 获取事件目标
    var target = EventUtil.getTarget(event);

    switch(target.id) {
        case "dosomething":
            document.title = "i changed the document's title";
            break;
        case "gosomewhere":
            location.href = "http://xxx.com";
        case "sayHi" :
            alert('hi');
            break;
    }
})

由于点击<li>元素都会冒泡到上级元素<ul>,我们为<ul>元素添加一个onclick事件处理程序,即单击事件最终会被这个函数处理。

这种技术占用的内存更少。所有用到按钮的事件都适合采用事件委托技术。
如果可行的话,可以考虑给document对象添加一个事件处理程序,用以处理页面上发生的某种特定类型的事件。该方式的好处在于:

  • document对象很快就被访问,而且在页面生命周期的任何时点上为它添加事件处理程序(无须等待DOMContentLoaded或load事件)。换句话说,只要可单击的元素呈现在页面上,就可以立即具备适当的功能。
  • 在页面中设置事件处理程序所需的事件更少。只需要一个事件处理程序所需的DOM引用更少,所花的事件也更少。
  • 整个页面占用的内存空间更少,能够提升整体性能。