jacascript 事件流

前言:这是笔者学习之后自己的理解与整理。如果有错误或者疑问的地方,请大家指正,我会持续更新!

事件流

  当浏览器发展到第四代时(IE4及Netscape4),浏览器开发团队遇到了一个很有意思的问题:页面的哪一部分会拥有某个特定的事件?想象画在一张纸上的一组同心圆。如果把手指放在圆心上,那么手指指向的不是一个圆,而是纸上的所有圆。

  两家公司的浏览器开发团队在看待浏览器事件方面还是一致的。如果单击了某个按钮,他们都认为单击事件不仅仅发生在按钮上,甚至也单击了整个页面。

  但有意思的是,IE 和 Netscape 开发团队居然提出了差不多是完全相反的事件流的概念。IE 的事件流是事件冒泡流,而 Netscape 的事件流是事件捕获流。

  事件流又称为事件传播,描述的是从页面中接收事件的顺序。DOM2 级事件规定的事件流包括三个阶段:事件捕获阶段(capture phase)、处于目标阶段(target phase)和事件冒泡阶段(bubbling phase)。

  首先发生的是事件捕获,为截获事件提供了机会。然后是实际的目标接收到事件,最后一个阶段是冒泡阶段,可以在这个阶段对事件做出响应。

  默认是在冒泡阶段对事件做出响应。

事件冒泡

  IE 的事件流叫做事件冒泡(event bubbling),即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到 window 对象;

  所有现代浏览器都支持事件冒泡,但在具体实现在还是有一些差别。IE9、Firefox、Chrome、Safari将事件一直冒泡到 window 对象;

事件捕获

  事件捕获的思想是 window 对象应该更早接收到事件,而最具体的节点应该最后接收到事件。事件捕获的用意在于在事件到达预定目标之前就捕获它;

  addEventListener() 方法中的第三个参数是指在冒泡阶段还是捕获阶段处理事件处理程序,设置为 true 时,即为捕获阶段,默认为 false 冒泡阶段;

HTML事件处理程序

  某个元素支持的每种事件,都可以使用一个与相应事件处理程序同名的 HTML 特性来指定。这个特性的值应该是能够执行的 javascript 代码;

  在事件处理程序函数内部,this值等于事件的目标元素;

  缺点1:因为用户可能会有HTML元素一出现在页面上时就触发相应的事件,但当时的事件处理程序有可能尚不具备执行条件,就会报错;

  缺点2:客户端编程的通用风格是保持 HTML 内容和 javaScript 行为分离,所以应该避免使用 HTML 事件处理程序属性,因为这些属性直接混合了 javascript 和 HTML,且不易扩展;

DOM0级事件处理程序

  通过 javascript 指定事件处理程序的传统方式,就是将一个函数赋值给一个事件处理程序属性。这种为事件处理程序赋值的方法是在第四代Web浏览器中出现的,而且至今仍然为所有现代浏览器所支持。原因一是简单,二是具有跨浏览器的优势。

  每个元素都有自己的事件处理程序属性,这些属性通常全部小写,将这种属性的值设置为一个函数,就可以指定事件处理程序。

  以DOM0级方式添加的事件处理程序会在事件流的冒泡阶段被处理;

  可以通过将事件处理程序属性设置为 null 来删除事件处理程序;

  缺点:DOM0级事件处理程序的缺点是围绕着每个事件目标对于每种事件类型只能添加一个事件处理程序。

        <div id="box" style="height:30px;width:200px;background-color:pink;"></div>
        <script>
            var oBox = document.getElementById(‘box‘);
            oBox.onclick = function(){
                this.innerHTML += ‘DOM0级事件处理程序‘;
            }
        </script> 

DOM2级事件处理程序

  DOM2级事件处理程序定义了两个方法用于处理指定和删除事件处理程序的操作:addEventListener() 和 removeEventListener()。IE8及以下浏览器不支持DOM2级事件处理程序。

  使用DOM2级事件处理程序的好处是可以添加多个事件处理程序,并按照他们添加的顺序触发;

        <div id="box" style="height:200px;width:200px;background-color:pink;"></div>
        <script>
            var oBox = document.getElementById(‘box‘);
            oBox.addEventListener(‘click‘,function(){
                this.innerHTML += ‘使用DOM2级事件处理程序的好处是可以添加多个事件处理程序<br/>‘;
            });
            oBox.addEventListener(‘click‘,function(){
                this.innerHTML += ‘并按照他们添加的顺序触发,第三个参数默认为false,所以是事件冒泡的顺序‘;
            });
        </script>  

  所有DOM节点中都包含这两个方法,并且它们都接受3个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。

  最后的布尔值参数如果是 true,表示在捕获阶段调用事件处理程序;如果是 false,表示在冒泡阶段调用事件处理程序。若最后的布尔值不填写,则默认为 false。

        <div id="box" style="height:200px;width:200px;background-color:pink;">
            <div id="child" style="height: 100px;width: 100px;background-color: green;"></div>
        </div>
        <script>
            var oBox = document.getElementById(‘box‘);
            var oChild = document.getElementById(‘child‘);
            oBox.addEventListener(‘click‘,function(){
                console.log(‘事件捕获顺序 先oBox‘);
            },true);
            oChild.addEventListener(‘click‘,function(){
                console.log(‘事件捕获顺序 后oChild‘);
            },true);
        </script> 

  若最后的布尔值不填写,则和 false 效果一样。

        <script>
            var oBox = document.getElementById(‘box‘);
            var oChild = document.getElementById(‘child‘);
            oBox.addEventListener(‘click‘,function(){
                console.log(‘事件冒泡顺序 后oBox‘);
            });
            oChild.addEventListener(‘click‘,function(){
                console.log(‘事件冒泡顺序 先oChild‘);
            });
        </script>

  通过 addEventListener() 添加的事件处理程序只能使用 removeEventListener() 来移除,移除时传入的参数与添加处理程序时使用的参数相同。addEventListener() 添加的匿名函数将无法移除;

        <div id="box" style="height:200px;width:200px;background-color:pink;"></div>
        <script>
            var oBox = document.getElementById(‘box‘);
            oBox.addEventListener("click",function(){
                this.innerHTML += ‘removeEventListener()无法移除匿名函数‘;
            },false);
            oBox.removeEventListener(‘click‘,function(){
                this.innerHTML += ‘removeEventListener()无法移除匿名函数‘;
            },false);
        </script>

IE事件处理程序

  IE实现了与DOM中类似的两个方法:attachEvent() 和 detachEvent()。这两个方法接受相同的两个参数:事件处理程序名称与事件处理程序函数。由于IE8及以下浏览器只支持事件冒泡,所以通过 attachEvent() 添加的事件处理程序都会被添加到事件冒泡阶段;

  attachEvent() 方法的第一个参数是"onclick",而非DOM的 addEventListener()方法中的"click";

  与其他三个事件处理程序不同,IE事件处理程序的 this 指向 window,而非被绑定事件的元素;

  使用 attachEvent() 方法添加的事件处理程序的触发顺序是有区别的。IE9、10浏览器是按正序执行的,而IE8及以下浏览器则是按倒序执行的;

        <div id="box" style="height:30px;width:200px;background-color:pink;"></div>
        <script>
            var oBox = document.getElementById(‘box‘);
            oBox.attachEvent(‘onclick‘,function(){
                this.innerHTML += ‘attachEvent()方法的第一个参数是"onclick"‘;

                //与其他三个事件处理程序不同,IE事件处理程序的this指向window,而非被绑定事件的元素
                console.log(this);//window
            })
        </script>

  使用 attachEvent() 添加的事件可以通过 detachEvent() 来移除,条件是必须提供相同的参数。与DOM2级事件处理程序一样,这也意味着添加的匿名函数将不能被移除。不过,只要能够将对相同函数的引用传给 detachEvent(),就可以移除相应的事件处理程序。

        <div id="box" style="height:30px;width:200px;background-color:pink;"></div>
        <script>
            var oBox = document.getElementById(‘box‘);
            oBox.attachEvent("onclick",function(){
                box.innerHTML += ‘与DOM2级事件处理程序一样,attachEvent添加的匿名函数将不能被移除‘;
            },false);
            oBox.detachEvent(‘onclick‘,function(){
                box.innerHTML += ‘与DOM2级事件处理程序一样,attachEvent添加的匿名函数将不能被移除‘;
            },false);
        </script>

事件执行顺序

  如果同时出现 HTML 事件处理程序和 DOM0 级事件处理程序,DOM0 级会覆盖 HTML 事件处理程序;

  chrome/opera/safari等 webkit 内核的浏览器会按照事件处理程序出现的顺序来排列,所以结果为:DOM2级 DOM0级

  firefox 浏览器和 IE 浏览器会将 DOM0 级事件优先调用,所以 firefox 和 IE11 浏览器结果为:DOM0级 DOM2级

  IE9、10浏览器结果为:DOM0级 DOM2级 IE

  IE8及以下浏览器结果为:DOM0级 IE

时间: 2024-07-29 18:38:58

jacascript 事件流的相关文章

粗浅的总结下事件流

什么是事件流?以及为什么要有事件流? 简单的说,事件流就是,确认触发条件满足时,事件对应函数的调用顺序.举个例子,鼠标光标在某个按钮上点击了,按钮又绑定了mousedown事件,那么其对应的函数就会调用.而其实,光标落下的位置也在document.window的范围内,或许还可能在其他元素的和模型内.如果这些元素也都绑定了mousedown事件,那么哪个元素的mousedown事件对应的函数先调用呢?这就需要确认一个发生的顺序问题. 具体的说,事件流分为三个阶段,即捕获阶段.目标(处理)阶段.冒

从click事件理解DOM事件流

事件流是用来解释页面上的不同元素接受一个事件的顺序,首先要明确两点: 1.一个事件的影响元素可能不止一个(同心圆理论),但目标元素只有一个. 2.如果这些元素都绑定了相同名称的事件函数,我们怎么知道这些函数的运行顺序?于是有了事件流的概念(事件捕捉,事件冒泡) 举个例子: <div id="outer"> <p id="inner">Click me!</p> </div> 为了看起来方便,先无视CSS样式,那么蓝色的

JS事件流

事件流:当页面元素触发事件的时候,该元素的容器以及整个页面都会按照特定顺序响应该元素的触发事件,事件传播的顺序叫做事件流. 一.事件流的分类 1.冒泡型事件(所有的浏览器都支持 w3c标准) 由明确的事件源到最不确定的事件源依次向上触发. 2.捕获型事件(IE不支持 w3c标准 火狐) 不确定的事件源到明确的事件源依次向下触发. addEventListener(事件,处理函数,false) addEventListener(事件,处理函数,true) 二.阻止事件流 IE: 事件对象.canc

浅谈js之事件流

这些日子我就把js的相关知识梳理一下,今天来说javascript中的事件流. 1.事件流 事件流:从页面中接收事件的顺序.也就是说当一个事件产生时,这个事件的传播过程,就是事件流. IE的事件流 IE中的事件流叫事件冒泡:事件冒泡:事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点(文档).对于html来说,就是当一个元素产生了一个事件,它会把这个事件传递给它的父元素,父元素接收到了之后,还要继续传递给它的上一级元素,就这样一直传播到document对象(亲测现在的浏览器到win

理解JavaScript中的事件流

原文地址:http://my.oschina.net/sevenhdu/blog/332014 目录[-] 事件冒泡 事件捕获 DOM事件流 当浏览器发展到第四代时(IE4和Netscape Communicator 4),浏览器团队遇到一个很有意思的问题:页面的哪一部分会拥有特定的事件?想象下在一张纸上有一组同心圆,如果你把手指放在圆心上,那么你的手指指向的不是一个圆,而是一组圆.两家公司的开发团队在看待浏览器事件方面还是一致的.如果你单击了某个按钮,那么同时你也单击了按钮的容器元素,甚至整个

jacascript 事件对象event

前言:这是笔者学习之后自己的理解与整理.如果有错误或者疑问的地方,请大家指正,我会持续更新! 在触发DOM上的某个事件时,会产生一个事件对象 event,这个对象中包含着所有与事件有关的信息.所有浏览器都支持 event 对象,但有兼容性问题. 获取事件对象 一般地,event 对象是事件程序的第一个参数.IE8及以下浏览器不支持: 另一种方法是直接使用 event 变量,firefox 浏览器不支持: 获取事件对象的常见兼容写法: <div id="box" style=&qu

事件流及事件冒泡机制

事件流 "DOM2级事件"规定的事件流包括三个阶段: 事件捕获阶段(为截获事件提供了机会) 处于目标阶段(实际的目标接收到事件) 事件冒泡阶段(可以在这个阶段对事件做出响应) IE9.Opera.Firefox.Chrome 和 Safari 都支持 DOM 事件流:IE8 及更早版本不支持 DOM 事件流. 事件冒泡机制 a.在一个对象上触发某类事件(比如单击onclick事件),如果此对象定义了此事件的处理程序,那么此事件就会调用这个处理程序,如果没有定义此事件处理程序或者事件返回

三言两语之js事件、事件流以及target、currentTarget、this那些事

厉害了我的哥——你是如此简单我却将你给遗忘   放假前再看某文档,里边提到两个我既熟悉又陌生的概念target.currentTarget,说他熟悉我曾经看到过这两个事件对象的异同处,说他陌生吧?很不巧.正要运用了,吾才发现吾压根就没记住...其实要讲清楚target.currentTarget,我们就不得不说一下事件流这个概念,而要言明事件流,我们也要晓得一下神马是事件以及一些周边生态概念,这三个概念是必须放在一块说,我们才能对能对这部分的知识有很好的理解滴,网上信息太零散,于是乎就有了这篇算

DOM事件探秘之事件流与事件处理程序

1.事件流:描述的是从页面中接受事件的顺序 ①.事件冒泡流:即时间最开始由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播至最不具体的那个节点(文档).      栗子:若<body><div><input type="button"/></div></body>次结构,点击按钮时,默认点了按钮的容器 默认点了body,默认点了html,默认点了document. ②.事件捕获:不太具体的节点应该更早接收到事