首页 > 代码库 > 深入理解DOM事件机制系列第三篇——事件对象

深入理解DOM事件机制系列第三篇——事件对象

×
目录
[1]获取 [2]事件类型 [3]事件目标[4]事件代理[5]事件冒泡[6]事件流[7]默认行为

前面的话

  在触发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含着所有与事件有关的信息。所有浏览器都支持event对象,但支持方式不同。本文将详细介绍事件对象

 

获取事件对象

  【1】一般地,event对象是事件程序的第一个参数

  [注意]IE8-浏览器不支持

//IE8-浏览器输出undefined,其他浏览器则输出事件对象[object MouseEvent]<div id="box" style="height:30px;width:200px;background:pink;"></div><script>var oBox = document.getElementById(box);oBox.onclick = function(a){    box.innerHTML = a;}</script>

<iframe style="width: 100%; height: 50px;" src="http://sandbox.runjs.cn/show/xzijhd0g" frameborder="0" width="320" height="240"></iframe>

  【2】另一种方法是直接使用event变量

  [注意]firefox浏览器不支持

//firefox浏览器输出undefined,其他浏览器则输出事件对象[object MouseEvent]  <div id="box" style="height:30px;width:200px;background:pink;"></div><script>var oBox = document.getElementById(box);oBox.onclick = function(){    box.innerHTML = event;}</script>

<iframe style="width: 100%; height: 50px;" src="http://sandbox.runjs.cn/show/0r7jsnqn" frameborder="0" width="320" height="240"></iframe>

兼容

  于是,对于获取事件对象的常见兼容写法如下

<div id="box" style="height:30px;width:200px;background:pink;"></div><script>var oBox = document.getElementById(box);oBox.onclick = function(e){    e = e || event;    box.innerHTML = e;}</script>

<iframe style="width: 100%; height: 50px;" src="http://sandbox.runjs.cn/show/smhj5ank" frameborder="0" width="320" height="240"></iframe>

属性和方法

  事件对象包含与创建它的特定事件有关的属性和方法。触发的事件类型不一样,可用的属性和方法也不一样。不过,所有事件都有些共有的属性和方法

事件类型

  事件有很多类型,事件对象中的type属性表示被触发的事件的类型

<div id="box" style="height:30px;width:200px;background:pink;"></div><script>//鼠标移入时,显示mouseover;移出时,显示mouseout;点击时,显示clickvar oBox = document.getElementById(box);oBox.onclick = oBox.onmouseout =oBox.onmouseover =function(e){    e = e || event;    box.innerHTML = e.type;}</script>

<iframe style="width: 100%; height: 50px;" src="http://sandbox.runjs.cn/show/wdc0qgbe" frameborder="0" width="320" height="240"></iframe>

  通过点击或按tab键将焦点切换到button按钮上可以触发focus事件

<button id="box" style="height:30px;width:200px;background:pink;"></button><script>var oBox = document.getElementById(box);oBox.onfocus = function(e){    e = e || event;    box.innerHTML = e.type;}</script>

<iframe style="width: 100%; height: 50px;" src="http://sandbox.runjs.cn/show/0t4a1egv" frameborder="0" width="320" height="240"></iframe>

事件目标

  关于事件目标,共有currentTarget、target和srcElement这三个属性

currentTarget

  currentTarget属性返回事件当前所在的节点,即正在执行的监听函数所绑定的那个节点

  [注意]IE8-浏览器不支持

  一般地,currentTarget与事件中的this指向相同。但在attachEvent()事件处理程序中,this指向window,详细信息移步至此

<style>.in{height: 30px;background-color: lightblue;margin:0 10px;}</style><ul id="box">    <li class="in">1</li>    <li class="in">2</li></ul><script>box.onclick = function(e){    e = e || event;    var tags =  box.getElementsByTagName(li);    tags[0].innerHTML = e.currentTarget;    tags[1].innerHTML = (e.currentTarget === this);}</script>

<iframe style="width: 100%; height: 90px;" src="http://sandbox.runjs.cn/show/8vlache4" frameborder="0" width="320" height="240"></iframe>

target

  currentTarget属性返回事正在执行的监听函数所绑定的节点,而target属性返回事件的实际目标节点

  [注意]IE8-浏览器不支持

  以下代码中,点击该实际目标节点时,颜色变品红;移出时,颜色变浅蓝

<style>#box{background-color: lightblue;}.in{height: 30px;}</style><ul id="box">    <li class="in">1</li>    <li class="in">2</li></ul><script>box.onclick = function(e){    e = e || event;    e.target.style.backgroundColor = pink;}box.onmouseout = function(e){    e = e || event;    e.target.style.backgroundColor = lightblue;}</script>

<iframe style="width: 100%; height: 90px;" src="http://sandbox.runjs.cn/show/vshdqmdt" frameborder="0" width="320" height="240"></iframe>

srcElement

  srcElement属性与target属性功能一致

  [注意]firefox浏览器不支持

<style>#box{background-color: lightblue;}.in{height: 30px;}</style><ul id="box">    <li class="in">1</li>    <li class="in">2</li></ul><script>box.onclick = function(e){    e = e || event;    e.srcElement.style.backgroundColor = pink;}box.onmouseout = function(e){    e = e || event;    e.srcElement.style.backgroundColor = lightblue;}</script>

<iframe style="width: 100%; height: 90px;" src="http://sandbox.runjs.cn/show/edab1jvn" frameborder="0" width="320" height="240"></iframe>

兼容 

var handler = function(e){    e = e || event;    var target = e.target || e.srcElement;}

 

事件代理

  由于事件会在冒泡阶段向上传播到父节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件。这种方法叫做事件的代理(delegation)

  事件代理应用事件目标的target和srcElement属性完成。利用事件代理,可以提高性能及降低代码复杂度

  有一个需求,一个<ul>中有5个<li>,移入时变浅蓝,移出时变品红

  下面分别用常规方法和事件代理方法来实现

<style>#box{background-color: pink;}.in{height: 30px;}</style><ul id="box">    <li class="in">1</li>    <li class="in">2</li>    <li class="in">3</li>    <li class="in">4</li>    <li class="in">5</li></ul><script>//常规方法var tags = box.getElementsByTagName(‘li‘);for(var i = 0; i < tags.length; i++){    tags[i].onmouseover = function(e){        this.style.backgroundColor = ‘lightblue‘;    }    tags[i].onmouseout = function(e){        this.style.backgroundColor = ‘pink‘;    }}</script><script>//事件代理方法box.onmouseover = function(e){    e = e || event;    var target = e.target || e.srcElement;    target.style.backgroundColor = ‘lightblue‘;}box.onmouseout = function(e){    e = e || event;    var target = e.target || e.srcElement;    target.style.backgroundColor = ‘pink‘;}</script>

<iframe style="width: 100%; height: 190px;" src="http://sandbox.runjs.cn/show/quqrt7ed" frameborder="0" width="320" height="240"></iframe>

事件冒泡

  事件冒泡是事件流的第三个阶段,通过事件冒泡可以在这个阶段对事件做出响应

  关于冒泡,事件对象中包含bubbles、cancelBubble、stopPropagation()和stopImmediatePropagation()这四个相关的属性和方法

bubbles

  bubbles属性返回一个布尔值,表示当前事件是否会冒泡。该属性为只读属性

  发生在文档元素上的大部分事件都会冒泡,但focus、blur和scroll事件不会冒泡。所以,除了这三个事件bubbles属性返回false外,其他事件该属性都为true

<button id="test" style="height: 30px;width: 200px;"></button><script>//点击按钮时,按钮内容为true,说明click事件默认可冒泡test.onclick = function(e){    test.innerHTML =e.bubbles;//true}</script>

<iframe style="width: 100%; height: 50px;" src="http://sandbox.runjs.cn/show/ynuxzfbz" frameborder="0" width="320" height="240"></iframe>

<div id="test" style="height: 50px;width: 200px;overflow:scroll;background:pink;line-height:60px;">内容</div><script>//滚动时,div内容变成false,说明scroll事件默认不可冒泡test.onscroll = function(e){    test.innerHTML =e.bubbles;//false}</script>

<iframe style="width: 100%; height: 100px;" src="http://sandbox.runjs.cn/show/lyjlbuu3" frameborder="0" width="320" height="240"></iframe>

stopPropagation()

  stopPropagation()方法表示取消事件的进一步捕获或冒泡,无返回值

  [注意]IE8-浏览器不支持

<button id="test" style="height: 30px;width: 200px;"></button><script>//点击按钮时,按钮内容为‘button‘,因为阻止了<button>向<body>的冒泡test.onclick = function(e){    e = e || event;    e.stopPropagation();    test.innerHTML +=button\n;}document.body.onclick = function(e){    test.innerHTML += body\n}</script>

<iframe style="width: 100%; height: 50px;" src="http://sandbox.runjs.cn/show/beaq8e9f" frameborder="0" width="320" height="240"></iframe>

stopImmediatePropagation()

  stopImmediatePropagation()方法不仅可以取消事件的进一步捕获或冒泡,而且可以阻止同一个事件的其他监听函数被调用,无返回值

  [注意]IE8-浏览器不支持

  使用stopIPropagation()方法,可以阻止冒泡,但无法阻止同一事件的其他监听函数被调用

<button id="test" style="height: 30px;width: 200px;"></button><script>//使用stopIPropagation()方法,<button>内部变为‘button‘,且背景颜色变成浅蓝test.addEventListener(click,function(e){    e = e || event;    e.stopPropagation();    test.innerHTML +=button\n;    })test.addEventListener(click,function(e){    e = e || event;    test.style.background = lightblue;    })document.body.onclick = function(e){    test.innerHTML += body\n}</script>

<iframe style="width: 100%; height: 50px;" src="http://sandbox.runjs.cn/show/9pipbllo" frameborder="0" width="320" height="240"></iframe>

  使用stopImmediatePropagation()方法,即可以阻止冒泡,也可以阻止同一事件的其他监听函数被调用

<button id="test" style="height: 30px;width: 200px;"></button><script>//使用stopImmediatePropagation()方法,<button>内部变为‘button‘,且背景颜色不变test.addEventListener(click,function(e){    e = e || event;    e.stopImmediatePropagation();    test.innerHTML +=button\n;    })test.addEventListener(click,function(e){    e = e || event;    test.style.background = lightblue;    })document.body.onclick = function(e){    test.innerHTML += body\n}</script>

<iframe style="width: 100%; height: 50px;" src="http://sandbox.runjs.cn/show/uqaxcbeh" frameborder="0" width="320" height="240"></iframe>

cancelBubble

  cancelBubble属性只能用于阻止冒泡,无法阻止捕获阶段。该值可读写,默认值是false。当设置为true时,cancelBubble可以取消事件冒泡

  [注意]该属性全浏览器支持,但并不是标准写法

<button id="test" style="height: 30px;width: 200px;"></button><script>test.onclick = function(e){    e = e || event;    e.cancelBubble = true;    test.innerHTML +=button\n;}document.body.onclick = function(e){    test.innerHTML += body\n}</script>

<iframe style="width: 100%; height: 50px;" src="http://sandbox.runjs.cn/show/iwqvtxaa" frameborder="0" width="320" height="240"></iframe>

  当使用stopIPropagation()方法或stopImmediatePropagation()方法时,关于cancelBubble值的变化,各浏览器表现不同

//chrome/safari/opera中,cancelBubble的值为false//IE9+/firefox中,cancelBubble的值为true<button id="test" style="height: 30px;width: 200px;"></button><script>test.onclick = function(e){    e = e || event;    e.stopPropagation();    test.innerHTML = e.cancelBubble;}</script>    

<iframe style="width: 100%; height: 50px;" src="http://sandbox.runjs.cn/show/hwy3eovc" frameborder="0" width="320" height="240"></iframe>

兼容

var handler = function(e){    e = e || event;    if(e.stopPropagation){        e.stopPropagation();    }else{        e.cancelBubble = true;    }}

 

事件流

eventPhase

  eventPhase属性返回一个整数值,表示事件目前所处的事件流阶段

  0表示事件没有发生,1表示捕获阶段,2表示目标阶段,3表示冒泡阶段

  [注意]IE8-浏览器不支持

【1】以下代码返回2,表示处于目标阶段

<button id="test" style="height: 30px;width: 200px;"></button><script>test.onclick = function(e){    e = e || event;    test.innerHTML = e.eventPhase;}</script>

<iframe style="width: 100%; height: 50px;" src="http://sandbox.runjs.cn/show/v1fb0jkl" frameborder="0" width="320" height="240"></iframe>

【2】以下代码返回1,表示处于捕获阶段

<button id="test" style="height: 30px;width: 200px;"></button><script>document.addEventListener(click,function(e){    e = e || event;    test.innerHTML = e.eventPhase;},true);</script>

<iframe style="width: 100%; height: 50px;" src="http://sandbox.runjs.cn/show/ne790bzy" frameborder="0" width="320" height="240"></iframe>

【3】以下代码返回3,表示处于冒泡阶段

<button id="test" style="height: 30px;width: 200px;"></button><script>document.addEventListener(click,function(e){    e = e || event;    test.innerHTML = e.eventPhase;},false);</script>

<iframe style="width: 100%; height: 50px;" src="http://sandbox.runjs.cn/show/kdhai6jn" frameborder="0" width="320" height="240"></iframe>

取消默认行为

  常见的默认行为有点击链接后,浏览器跳转到指定页面;或者按一下空格键,页面向下滚动一段距离

  关于取消默认行为的属性包括cancelable、defaultPrevented、preventDefault()和returnValue

  点击下列锚点时,会自动打开博客园首页

<a id="test" href="http://www.cnblogs.com" target="_blank">链接</a>

<iframe style="width: 100%; height: 40px;" src="http://sandbox.runjs.cn/show/fkczgq4g" frameborder="0" width="320" height="240"></iframe>

cancelable

  cancelable属性返回一个布尔值,表示事件是否可以取消。该属性为只读属性。返回true时,表示可以取消。否则,表示不可取消

  [注意]IE8-浏览器不支持

<a id="test" href="#">链接</a><script>test.onclick= function(e){    e = e || event;    test.innerHTML = e.cancelable;}</script>

<iframe style="width: 100%; height: 40px;" src="http://sandbox.runjs.cn/show/xdfqaubs" frameborder="0" width="320" height="240"></iframe>

preventDefault()

  preventDefault()方法取消浏览器对当前事件的默认行为,无返回值

  [注意]IE8-浏览器不支持

<a id="test" href="http://www.cnblogs.com">链接</a><script>test.onclick= function(e){    e = e || event;    e.preventDefault();}</script>

<iframe style="width: 100%; height: 40px;" src="http://sandbox.runjs.cn/show/hkuhaf2i" frameborder="0" width="320" height="240"></iframe>

returnValue

  returnValue属性可读写,默认值是true,但将其设置为false就可以取消事件的默认行为,与preventDefault()方法的作用相同

  [注意]firefox和IE9+浏览器不支持

<a id="test" href="http://www.cnblogs.com">链接</a><script>test.onclick= function(e){    e = e || event;    e.returnValue = false;}</script>

<iframe style="width: 100%; height: 40px;" src="http://sandbox.runjs.cn/show/5twjpudf" frameborder="0" width="320" height="240"></iframe>

兼容

var handler = function(e){    e = e || event;    if(e.preventDefault){        e.preventDefault();    }else{        e.returnValue = http://www.mamicode.com/false;>

return false

  除了以上方法外,取消默认事件还可以使用return false

<a id="test" href="http://www.cnblogs.com">链接</a><script>test.onclick= function(e){    return false;}</script>

<iframe style="width: 100%; height: 40px;" src="http://sandbox.runjs.cn/show/cmg9k2oa" frameborder="0" width="320" height="240"></iframe>

defaultPrevented

  defaultPrevented属性表示默认行为是否被阻止,返回true时表示被阻止,返回false时,表示未被阻止

  [注意]IE8-浏览器不支持

<a id="test" href="http://www.cnblogs.com">链接</a><script>test.onclick= function(e){    e = e || event;    if(e.preventDefault){        e.preventDefault();    }else{        e.returnValue = false;    }    test.innerHTML = e.defaultPrevented;}</script>

<iframe style="width: 100%; height: 40px;" src="http://sandbox.runjs.cn/show/idqixisk" frameborder="0" width="320" height="240"></iframe>

<script type="text/javascript">// 0){ return; } if(select[i].getBoundingClientRect().top <= 0 && select[i+1]){ if(select[i+1].getBoundingClientRect().top > 0){ change(oCon.children[i+2]) } }else{ change(oCon.children[select.length+1]) } }}document.body.onmousewheel = wheel;document.body.addEventListener(‘DOMMouseScroll‘,wheel,false);var oCon = document.getElementById("content");var close = oCon.getElementsByTagName(‘span‘)[0];close.onclick = function(){ if(this.innerHTML == ‘显示目录‘){ this.innerHTML = ‘ב; this.style.background = ‘‘; oCon.style.border = ‘2px solid #ccc‘; oCon.style.width = ‘‘; oCon.style.height = ‘‘; oCon.style.overflow = ‘‘; oCon.style.lineHeight = ‘30px‘; }else{ this.innerHTML = ‘显示目录‘; this.style.background = ‘#3399ff‘; oCon.style.border = ‘none‘; oCon.style.width = ‘60px‘; oCon.style.height = ‘30px‘; oCon.style.overflow = ‘hidden‘; oCon.style.lineHeight = ‘‘; }}for(var i = 2; i < oCon.children.length; i++){ oCon.children[i].onmouseover = function(){ this.style.color = ‘#3399ff‘; } oCon.children[i].onmouseout = function(){ this.style.color = ‘inherit‘; if(this.mark){ this.style.color = ‘#3399ff‘; } } oCon.children[i].onclick = function(){ change(this); } }function change(_this){ for(var i = 2; i < oCon.children.length; i++){ oCon.children[i].mark = false; oCon.children[i].style.color = ‘inherit‘; oCon.children[i].style.textDecoration = ‘none‘; oCon.children[i].style.borderColor = ‘transparent‘; } _this.mark = true; _this.style.color = ‘#3399ff‘; _this.style.textDecoration = ‘underline‘; _this.style.borderColor = ‘#2175bc‘; }// ]]></script>

深入理解DOM事件机制系列第三篇——事件对象