DOM(Document Object Model) 即文档对象模型,是针对 html 和 XML 文档的一个 API,DOM 描绘了一个层次化的节点树,允许开发人员进行添加、移除和修改页面的某一部分。
,如果在 HTML 中就是 onclick 属性上加一个 JS 语句。 删除 DOM0 事件处理程序,只要将对应事件属性置为 null 即可,即
- element.onclick=function(){ }
。
- element.onclick=null
。最后一个参数为 true 的时候表示在捕获阶段调用程序,如果是 false,表示在冒泡阶段调用事件处理程序。 删除 DOM2 事件处理程序,用 removeEventListener 实现。 IE 中的 DOM2 级事件处理使用了 attachEvent 来实现,IE9 以下版本只支持冒泡事件,所以 attachEvent 添加的事件都是冒泡阶段。attachEvent 添加的事件第一个参数是 onclick 而非标准事件中的 click。使用 detachEvent 实现删除事件。
- element.addEventListener('click', function(){}, false)
- element.addEventListener('keyup', function(){}, false)
因为 DOM1 主要专注于 HTML 文档和 XML 文档,没有涉及事件处理,所以事件处理直接从 DOM0 跳到 DOM2。
DOM 事件模型分为两类:一类是 IE 所使用的冒泡型事件(Bubbling);另一类是 DOM 标准定义的冒泡型与捕获型(Capture)的事件。除 IE 外的其他浏览器都支持标准的 DOM 事件处理模型。
DOM 事件模型
DOM 标准采用捕获 + 冒泡。两种事件流都会触发 DOM 的所有对象,从 document 对象开始,也在 document 对象结束。
DOM 事件流
标准 DOM 事件流包括三个阶段:事件捕获阶段,处于目标阶段和事件冒泡阶段
DOM 事件捕获具体流程
首先接收的是 window,然后是 ducument,再是 html 标签 (js 获取 html 节点用
),然后是 body,最后随着节点父子关系一级一级往下传,直到目标元素。 冒泡则相反,从目标元素到 window 一级一级往上。 通过代码来描述事件捕获过程:
- document.documentElement
- <div id="ev" style='width:100px;height: 100px;background: blue'></div>
- // 把打印顺序搅乱,以免误以为是因为执行顺序影响
- <script>
- var ev = document.getElementById('ev');
- ev.addEventListener('click', function (e) {
- console.log('ev captrue');
- }, true);
- window.addEventListener('click', function (e) {
- console.log('window captrue');
- }, true);
- document.addEventListener('click', function (e) {
- console.log('document captrue');
- }, true);
- document.body.addEventListener('click', function (e) {
- console.log('body captrue');
- }, true);
- document.documentElement.addEventListener('click', function (e) {
- console.log('html captrue');
- }, true);
- // 打印结果如下:
- // window captrue
- // document captrue
- // html captrue
- // body captrue
- // ev captrue
- </script>
通过代码来描述事件冒泡过程:
- <div id="ev" style='width:100px;height: 100px;background: blue'></div>
- // 把打印顺序搅乱,以免误以为是因为执行顺序影响
- <script>
- var ev = document.getElementById('ev');
- ev.addEventListener('click', function (e) {
- console.log('ev captrue');
- }, false);
- window.addEventListener('click', function (e) {
- console.log('window captrue');
- }, false);
- document.addEventListener('click', function (e) {
- console.log('document captrue');
- }, false);
- document.body.addEventListener('click', function (e) {
- console.log('body captrue');
- }, false);
- document.documentElement.addEventListener('click', function (e) {
- console.log('html captrue');
- }, false);
- // 打印结果如下:
- // ev captrue
- // body captrue
- // html captrue
- // document captrue
- // window captrue
- </script>
:阻止默认行为。常用的情况就是给一个 标签绑定了 click 事件,响应函数中设置了
- event.preventDefault()
,就阻止了链接跳转的行为。
- event.preventDefault()
:阻止冒泡行为。比如:一个父级元素绑定了一个事件,子元素绑定了另一个事件,如果想父级元素做一件事,子元素做一件事,两件事是分开的,互不影响,就需要给子元素事件中设置
- event.stopPropagation()
,否则子元素事件执行时,按照冒泡的原则,父级元素事件也会响应。
- event.stopPropagation()
:除了该事件的冒泡行为被阻止之外 (
- event.stopImmediatePropagation
方法的作用),该元素绑定的后序相同类型事件的监听函数的执行也将被阻止。如一个元素上绑定了 2 个 click 事件 a 和 b,如果给 a 函数中添加
- event.stopPropagation
后,则阻止 click 事件冒泡,并且阻止了 b 函数的执行。
- event.stopImmediatePropagation
- <p>1</p>
- <p>2</p>
- <p>3</p>
- <script>
- var ps = document.getElementsByTagName('p');
- for (var i = 0; i < ps.length; i++) {
- ps[i].addEventListener('click', func, false);
- }
- function func(e) {
- console.log(e.currentTarget); // 打印所点击对应的<p>节点
- // 该函数用作事件处理器时: this === e.currentTarget
- }
- </script>
- <ul id="ul">
- <li>1</li>
- <li>2</li>
- <li>3</li>
- </ul>
- <script>
- document.getElementById("ul").addEventListener('click', function(){
- console.log(event.target); // 当点击1时,打印<li>1</li>
- console.log(event.currentTarget); // 当点击1或2或3时,都打印整个<ul>
- });
- </script>
以上所讲都是 DOM 一些自带的事件,当然也可以自己定义一些事件。
- <div id="ev"></div>
- <script>
- var ev = document.getElementById('ev');
- var evt = new Event('test');
- ev.addEventListener('test', function () {
- console.log('test dispatch');
- });
- setTimeout(function () {
- ev.dispatchEvent(evt);
- }, 3000);
- // 打开页面3面后打印 'test dispatch'
- </script>
来源: http://www.jianshu.com/p/a13ed02ada40