DOM2级事件流规定的事件包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。
首先发生的是事件捕获。然后是实际的目标接收到事件。最后一个阶段是冒泡阶段。
addEventListener第一个参数是事件名,不带on前缀,第二个参数是绑定的函数,这个函数带有唯一的参数event,第三个参数为isCapture,是否捕获阶段执行的含义。当设置为false时在冒泡阶段执行,是我们常用的方式。因为我们可以对内层DIV绑定的事件函数中,执行event.stopPropagation()来阻止事件继续传递。
给一段JS示例代码:
<!DOCTYPE html> <html> <head> <title>js测试</title> </head> <body> <div id="outer"> 外层DIV <div id="inner">内层DIV</div> </div> <script> var outer = document.getElementById('outer'); var inner = document.getElementById('inner'); /** * addEventListener 为Dom元素绑定事件 * 参数1:事件名称(不以on开头) * 参数2:事件执行的函数 * 参数3:是否按捕获阶段执行,一般设置为false,冒泡阶段执行 * 说明: * DOM2级事件规定的事件流包括三个阶段。 * 第一个阶段是事件捕获阶段,从外往内传递; * 第二个阶段是处于目标阶段,这个阶段中参数3设置false或true都一样,按照绑定先后顺序执行。 * 第三个阶段是冒泡阶段,从内往外传递。 * 注意: * 以下的注释都针对点击一次“内层DIV” */ outer.addEventListener('click', function(event){ console.log('outer clicked! false 1'); // 最后执行,因为处于最外层的冒泡阶段,但如果点击“外层DIV”则最先执行 }, false); outer.addEventListener('click', function(event){ console.log('outer clicked! true 2'); // 最先执行因为处于外层捕获阶段,但如果点击“外层DIV”则第2执行 }, true); inner.addEventListener('click', function(event){ console.log('inner clicked! false 1'); // 第2执行,因为是目标 }, false); inner.addEventListener('click', function(event){ console.log('inner clicked! true 2'); // 第3执行,因为是目标 }, true); inner.addEventListener('click', function(event){ console.log('inner clicked! false 3'); // 第4执行,因为是目标 }, false); </script> </body> </html>
在上述代码中,打开控制台,如果点击“内层DIV”文字,会得到如下执行结果:
addEventListener 函数第三个参数设置为false是最常用的,绑定的函数将在冒泡阶段执行,设置为true则是在捕获阶段执行,但如果事件发生时,该DOM元素是目标元素,那么绑定函数则是在目标阶段执行,这时设置的true或false就毫无意义了,函数会按照绑定先后顺序执行。
这里可以看到,最外层DIV在捕获阶段的事件绑定函数最先得到执行。
然后是目标DIV按照先后顺序绑定的事件函数(跟第三个参数为false还是true毫无关系)。
最后才是最外层DIV的冒泡阶段绑定函数。
如果点击“外层DIV”,则得到如下结果:
这是执行顺序则是按绑定顺序来的,因为这时候两个函数已经不是针对冒泡阶段或捕获阶段了,都是目标阶段执行的。
事件传递顺序是: window -- document -- html -- body -- div ...
我们给代码增加window绑定事件,将看到,window处于最外层,捕获阶段最先执行,冒泡阶段最后执行。
<!DOCTYPE html> <html> <head> <title>js测试</title> </head> <body> <div id="outer"> 外层DIV <div id="inner">内层DIV</div> </div> <script> var outer = document.getElementById('outer'); var inner = document.getElementById('inner'); /** * addEventListener 为Dom元素绑定事件 * 参数1:事件名称(不以on开头) * 参数2:事件执行的函数 * 参数3:是否按捕获阶段执行,一般设置为false,冒泡阶段执行 * 说明: * DOM2级事件规定的事件流包括三个阶段。 * 第一个阶段是事件捕获阶段,从外往内传递; * 第二个阶段是处于目标阶段,这个阶段中参数3设置false或true都一样,按照绑定先后顺序执行。 * 第三个阶段是冒泡阶段,从内往外传递。 * 注意: * 以下的注释都针对点击一次“内层DIV” */ outer.addEventListener('click', function(event){ console.log('outer clicked! false 1'); // 最后执行,因为处于最外层的冒泡阶段,但如果点击“外层DIV”则最先执行 }, false); outer.addEventListener('click', function(event){ console.log('outer clicked! true 2'); // 最先执行因为处于外层捕获阶段,但如果点击“外层DIV”则第2执行 }, true); inner.addEventListener('click', function(event){ console.log('inner clicked! false 1'); // 第2执行,因为是目标 }, false); inner.addEventListener('click', function(event){ console.log('inner clicked! true 2'); // 第3执行,因为是目标 }, true); inner.addEventListener('click', function(event){ console.log('inner clicked! false 3'); // 第4执行,因为是目标 }, false); window.addEventListener('click', function(event){ console.log('window clicked! false'); }, false); window.addEventListener('click', function(event){ console.log('window clicked! true'); }, true); </script> </body> </html>
点击“内层DIV”,可以得到如下结果:
如果我们在window的捕获阶段事件绑定函数中增加event.stopPropagation();那么事件被扼杀在这个阶段。代码如下:
<!DOCTYPE html> <html> <head> <title>js测试</title> </head> <body> <div id="outer"> 外层DIV <div id="inner">内层DIV</div> </div> <script> var outer = document.getElementById('outer'); var inner = document.getElementById('inner'); /** * addEventListener 为Dom元素绑定事件 * 参数1:事件名称(不以on开头) * 参数2:事件执行的函数 * 参数3:是否按捕获阶段执行,一般设置为false,冒泡阶段执行 * 说明: * DOM2级事件规定的事件流包括三个阶段。 * 第一个阶段是事件捕获阶段,从外往内传递; * 第二个阶段是处于目标阶段,这个阶段中参数3设置false或true都一样,按照绑定先后顺序执行。 * 第三个阶段是冒泡阶段,从内往外传递。 * 注意: * 以下的注释都针对点击一次“内层DIV” */ outer.addEventListener('click', function(event){ console.log('outer clicked! false 1'); // 最后执行,因为处于最外层的冒泡阶段,但如果点击“外层DIV”则最先执行 }, false); outer.addEventListener('click', function(event){ console.log('outer clicked! true 2'); // 最先执行因为处于外层捕获阶段,但如果点击“外层DIV”则第2执行 }, true); inner.addEventListener('click', function(event){ console.log('inner clicked! false 1'); // 第2执行,因为是目标 }, false); inner.addEventListener('click', function(event){ console.log('inner clicked! true 2'); // 第3执行,因为是目标 }, true); inner.addEventListener('click', function(event){ console.log('inner clicked! false 3'); // 第4执行,因为是目标 }, false); window.addEventListener('click', function(event){ console.log('window clicked! false'); }, false); window.addEventListener('click', function(event){ event.stopPropagation(); console.log('window clicked! true'); }, true); </script> </body> </html>
执行结果如下:
注意:addEventListener在IE8中无效,IE8中只能使用attachEvent,对于attachEvent函数绑定事件函数时,只支持两个参数,这两个参数同addEventListener的前两个参数,第一个是事件名,但事件名比addEventListener来说要多一个前缀on,第二个是事件绑定函数,这个函数带有唯一的参数event。但attachEvent绑定的事件函数因为没有第三个参数,他们都是在冒泡阶段执行,而且默认先后顺序跟addEventListener正好相反,先绑定的后执行,后绑定的先执行。
相关推荐
例如,IE10及以下版本不支持事件捕获,而其他现代浏览器如IE11、Chrome、Firefox和Safari则同时支持捕获和冒泡。 JavaScript提供了`addEventListener`方法来添加事件监听器。该方法接受三个参数:事件名、处理函数...
在标准浏览器(如Chrome, Safari, Opera, Firefox)和IE9及更高版本中,事件传播同时支持捕获和冒泡。而在IE8及以下版本,只支持冒泡。为了处理事件,有以下两种方式: - **addEventListener()**:这是W3C标准的...
然而,在DOM2级事件规范中,目标元素在捕获阶段不会接收到事件,但在某些浏览器中,如Safari、Chrome、Firefox和Opera 9.5及以上版本,目标元素在捕获阶段也会触发事件处理程序。 4. 阻止事件冒泡: 在某些情况下...
主流的浏览器如Chrome、Firefox、Safari和IE都遵循标准的事件冒泡机制,但是处理细节上可能会有差异。例如,IE8及以下版本的浏览器采用的是事件捕获模型,而标准的事件模型是事件冒泡。 理解并掌握JavaScript的事件...
例如,在Firefox、Chrome、Safari和Opera中,对同一个事件重复注册相同的监听器只会保留一个,而IE会执行多次。此外,IE6和IE7的事件监听器执行顺序是随机的,而IE8及更高版本和其它现代浏览器则是按照注册顺序执行...
6. **浏览器兼容性**:提到插件兼容主流浏览器,这意味着开发者可能使用了polyfill或条件语句来确保在不同浏览器环境下(如Chrome、Firefox、Safari、Edge和旧版IE)的正常运行。 7. **readme.md**:这个文件通常是...
- **事件冒泡与捕获**:理解事件传播机制对于编写复杂的交互逻辑至关重要。 #### 常见功能实现 - **DOM的增删改查**:使用JavaScript操作DOM节点,实现动态更新页面内容。 - **遍历DOM**:遍历DOM树结构,查找特定...
- 它主要运行在浏览器环境中,如Chrome、Firefox、Safari等,但也有Node.js平台使其能在服务器端运行。 - JavaScript与Java名字相似,但两者并无直接关系,由 Netscape 的 Brendan Eich 创建。 2. **变量和数据...
随着DOM(Document Object Model)2级规范的发展,事件处理被标准化,现代浏览器如IE9、Firefox、Opera、Safari和Chrome均支持DOM2级事件模块。 JavaScript中有三种事件模型: 1. **内联模型(HTML事件处理程序)**...
在IE5.5之前的版本中,事件会直接从`body`跳到`document`,而在Firefox、Chrome和Safari中,事件会冒泡到`window`对象。 3. **阻止事件冒泡** 阻止事件冒泡意味着不让事件继续向父元素传递。这可以通过调用`event....
但在需要兼容各大主流浏览器(如Firefox、Chrome、Safari等)的环境下,开发者不能仅仅依赖于IE特有的事件。 为了解决跨浏览器的`mouseover`和`mouseout`事件冒泡问题,开发者们采用了各种方法。例如,可以利用W3C...
这种控件通常需要支持多种浏览器,因此开发者需要考虑浏览器的兼容性问题,如IE、Chrome、Firefox、Safari和Edge等。 在设计兼性好的日历控件时,以下是一些关键知识点: 1. **跨浏览器兼容性**:使用广泛接受的...
由于JavaScript在不同的浏览器中可能存在差异,因此实现一个兼容多浏览器的万年历功能需要考虑浏览器的兼容性问题,确保在IE、Chrome、Firefox、Safari等主流浏览器上都能正常运行。 万年历的设计通常包括以下几个...
- IE6/IE7对DOM操作的支持相对较弱,例如不支持`getElementsByClassName`,而Firefox等现代浏览器通常支持更多的DOM2级和DOM3级方法。 7. **CSS兼容性**: - 不同浏览器对CSS的解析也有所不同,可能需要使用特定...
而在非IE浏览器中,如Firefox、Chrome和Safari,事件的执行顺序是“先进后出”,即最后添加的事件先被执行。 `addEventListener`方法是DOM中用于添加事件监听器的标准方法,接受三个参数:事件类型、处理函数和布尔...
对于其他主流浏览器,如Firefox、Chrome、Safari和Opera,则使用addEventListener和removeEventListener方法。由于这两种方法的语法和使用方式不同,因此在实际开发中往往需要对不同浏览器进行兼容性处理,以确保...
不同的浏览器如Chrome、Firefox、Safari、Edge和Internet Explorer(IE)等,在解析JavaScript语法、DOM操作、事件处理、CSS样式等方面可能有各自的理解和实现。例如,一些浏览器可能支持新的ECMAScript特性,而旧...
MooTools致力于跨浏览器兼容性,确保在主流的浏览器(如IE6+、Firefox、Chrome、Safari和Opera)上都能正常工作。它通过抽象化浏览器差异,使得开发者无需关心底层的实现细节,更专注于应用逻辑。 八、压缩与非压缩...