————————————————————————————————————————————
事件
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
文档或浏览器窗口中发生一些特定的交互瞬间,我们可以通过侦听器(或处理程序)来预定事件,以便事件发生的时候执行相应的代码
基本概念:
- 事件类型(事件名字):说明发生什么类型事件的而字符串
- 事件目标:事件目标是发生的事件或与之相关的对象,必须同时指定类型和目标。Window、Document、Element对象是常见的事件目标,但某些事件也由其他类型的对象触发
- 事件处理程序、事件监听程序:响应某个事件的函数被称为事件处理程序或事件侦听器
- 事件对象:事件对象是与特定事件相关且包含有关该事件详细信息的对象,事件对象作为参数传递给事件处理程序函数。所有的事件对象都有用来指定事件类型的type属性和指定事件目标的target属性。每个事件类型都为其相关的事件对象定义一组属性。
- 事件传播:浏览器决定哪个对象触发其事件处理程序的过程。
事件模型:
-
内联模型:
- 事件处理函数是HTML标签的一个属性,用于处理指定事件
-
脚本模型:
- 在JavaScript中处理事件,但无法同时处理多个相同的点击事件
-
DOM2模型:
- "DOM2级事件"定义了两个方法,用于添加事件和删除事件处理程序的操作:addEventListener()和removeEventListener()。所有DOM节点中都包含这两个方法,并且它们都接受3个参数;事件名、函数、冒泡或捕获的布尔值(true表示捕获,false表示冒泡)。IE兼容性问题
调用事件三种模型写法
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <title></title> 6 <script type="text/javascript" src="test.js"></script> 7 </head> 8 9 <body> 10 <input type="button" value="test1" id="btn1"> 11 <input type="button" value="test2" id="btn2"> 12 <input type="button" value="test3" id="btn3"> 13 <input type="button" value="event" id="btn4"> 14 15 <!-- 脚本模型 --> 16 <!-- 无法执行多个事件处理 --> 17 <script type="text/javascript"> 18 // 获取id btn1的元素 19 var btn1 = document.getElementById('btn1'); 20 // 监听当btn1产生onclick时事件 21 btn1.onclick = function test1() { 22 console.log('this is button 1.') 23 } 24 25 // 另一种写法 26 var btn2 = document.getElementById('btn2'); 27 // p.s.此处function不加(),否则将直接调用,onclick只能获得function返回值 28 btn2.onclick = test2; 29 30 function test2() { 31 console.log('this is button 2.'); 32 console.log(this.tagName); 33 } 34 var count = 0; 35 btn3.onclick = function() { 36 console.log(++count); 37 if (count == 3) { 38 // 当单击事件指向null时即为删除之前的事件 39 btn3.onclick = null; 40 } 41 } 42 43 // 事件对象 44 // 在这里参数传的e即事件event,打印出来显示event类型 45 var btn4 = document.getElementById('btn4'); 46 btn4.onclick=function(e){ 47 // 在ie浏览器中需要这样 window.event; 48 var e = e||window.event; // 兼容所有浏览器的事件写法 49 console.log(e); 50 } 51 52 </script> 53 </body> 54 55 </html>
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
传统事件类型:
- 鼠标事件
- 键盘事件
-
事件对象 Event IE兼容性问题
- 常量
-
属性
- bubbles 返回布尔值,指示事件是否是起泡事件类型
- cancelable 返回布尔值,指示事件是否可拥可取消的默认动作
- currentTarget 返回其事件监听器触发该事件的元素
- eventPhase 返回事件传播的当前阶段
- target 返回触发此事件的元素(事件的目标节点)
- timeStamp 返回事件生成的日期和时间
- type 返回当前 Event 对象表示的事件的名称。
-
方法
- initEvent() 初始化新创建的 Event 对象的属性
- preventDefault() 通知浏览器不要执行与事件关联的默认动作
- stopPropagation() 不再派发事件。
target和currentTarget区别:
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <title></title> 6 <script type="text/javascript" src="EventUtil.js"></script> 7 </head> 8 9 <body> 10 <div id="box1" style="border:1px red solid;300px;height: 200px"> 11 <input type="button" value="btn1" id="btn1" style="margin:10px"> 12 </div> 13 <script type="text/javascript"> 14 var btn1 = document.getElementById('btn1'); 15 btn1.addEventListener('click', function(e) { 16 // currentTarget this target都指向这个button元素 17 console.log(e.currentTarget); 18 console.log(this); 19 console.log(e.target); 20 // 可以利用来修改样式 21 e.target.style.background = '#fff'; 22 }, false); 23 24 var box1 = document.getElementById('box1'); 25 box1.onclick = function(e) { 26 console.log("div:" + e.currentTarget); 27 console.log("div:" + this); 28 console.log("div:" + e.target); 29 } 30 31 document.body.onclick = function(e) { 32 console.log("body:" + e.currentTarget); 33 console.log("body:" + this); 34 console.log("body:" + e.target); 35 } 36 37 var box1 = document.getElementById('box1'); 38 document.onclick = function(e) { 39 console.log("document:" + e.currentTarget); 40 console.log("document:" + this); 41 console.log("document:" + e.target); 42 } 43 // target指向触发该事件的元素,currentTarget返回的是事件监听器触发的元素 44 // 当冒泡时候,点击btn1触发,在div监听器的target指向btn1,而currentTarget是div 45 </script> 46 </body> 47 48 </html>
eventPhase
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <title></title> 6 <script type="text/javascript" src="EventUtil.js"></script> 7 </head> 8 9 <body> 10 <div id="box1" style="border:1px red solid;300px;height: 200px"> 11 <input type="button" value="btn1" id="btn1" style="margin:10px"> 12 </div> 13 <script type="text/javascript"> 14 var btn1 = document.getElementById('btn1'); 15 var box1 = document.getElementById('box1'); 16 17 18 function handler(e) { 19 switch (e.type) { 20 case 'click': 21 e.target.style.background = '#000'; 22 break; 23 case 'mouseover': 24 e.target.style.background = 'yellow'; 25 break; 26 case 'mouseout': 27 e.target.style.background = 'blue'; 28 break; 29 } 30 } 31 box1.onclick = handler; 32 box1.onmouseover = handler; 33 box1.onmouseout = handler; 34 btn1.onclick = function(e) { 35 console.log("1:" + e.eventPhase); 36 }; 37 document.body.addEventListener('click', function(e) { 38 console.log("2:" + e.eventPhase); 39 }, true); 40 document.body.onclick = function(e) { 41 console.log("3:" + e.eventPhase); 42 }; 43 // 如果在捕获阶段调用时,返回1 44 // target在目标上时,返回2 45 // 处于冒泡阶段时,返回3 46 // 当点击btn1时,btn返回2,body返回13 47 // 当点击div时,body返回13,此时target不为body所以不返回2 48 // 当点击body时,body返回2 49 </script> 50 </body> 51 52 </html>
- 目标事件对象
- 框架/对象事件
- 表单事件
- 剪贴板事件
- 打印事件
- 拖动事件
- 动画事件
- 过渡时间
- 其他事件
- 事件监听对象
- 文档事件对象
- 鼠标/键盘事件对象
事件流:
- 事件流描述的是从页面中接收事件的顺序
- 当几个都具有时间的元素层叠在一起时,点击其中一个元素,所有的元素都会触发事件
-
两种模式
- 冒泡:从里往外逐个触发(主流浏览器、IE)
- 捕获:从外往里逐个触发(Netscape)
p.s.浏览器现在默认为冒泡模型,使用DOM2级模型的事件绑定机制才能手动定义事件流模式
冒泡事件流
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <title></title> 6 <script type="text/javascript" src="test.js"></script> 7 </head> 8 9 <body> 10 <div id="box1" style="border:1px red solid;300px;height: 200px"> 11 <input type="button" value="btn1" id="btn1" style="margin:10px"> 12 </div> 13 <script type="text/javascript"> 14 // 冒泡形式事件流 15 // botton -> div -> body -> documentElement -> document 16 var btn1 = document.getElementById('btn1'); 17 var box1 = document.getElementById('box1'); 18 btn1.onclick = function() { 19 alert('botton onclick'); 20 } 21 box1.onclick = function() { 22 alert('div onclick'); 23 } 24 document.body.onclick = function(e) { 25 alert('body onclick'); 26 // 取消冒泡(兼容模式) 27 // 如果ie取消冒泡模式为undefined说明是其他浏览器,则执行w3c取消冒泡 28 if (typeof e.cancelBubble == 'undefined') { 29 // w3c取消冒泡,取消冒泡后documentElement和document都无法冒泡显示 30 e.stopPropagation(); 31 } else { 32 // ie冒泡 33 e.cancelBubble() = true; 34 } 35 } 36 document.documentElement.onclick = function() { 37 alert('documentElement onclick'); 38 } 39 document.onclick = function() { 40 alert('document onclick'); 41 } 42 </script> 43 </body> 44 45 </html>
绑定事件和移除事件
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <title></title> 6 <script type="text/javascript" src="test.js"></script> 7 </head> 8 9 <body> 10 <div id="box1" style="border:1px red solid;300px;height: 200px"> 11 <input type="button" value="btn1" id="btn1" style="margin:10px"> 12 </div> 13 <script type="text/javascript"> 14 var btn1 = document.getElementById('btn1'); 15 var box1 = document.getElementById('box1'); 16 // 通过绑定事件addEventListener时,同一个元素多个相同事件会按顺序执行 17 btn1.addEventListener('click', function() { 18 alert('a'); 19 }, false); 20 var handler1 = function() { 21 alert('b'); 22 } 23 btn1.addEventListener('click', handler1, false); 24 btn1.addEventListener('click', function(e) { 25 alert('button click'); 26 // 取消冒泡 27 // var e = e || window.event; 28 // if (typeof e.cancelBubble == 'undefined') { 29 e.stopPropagation(); 30 // } else { 31 // e.cancelBubble = true; 32 // } 33 }, false); 34 box1.addEventListener('click', function() { 35 alert('div click'); 36 }, false); 37 document.body.addEventListener('click', function() { 38 alert('body click'); 39 }, false); 40 document.documentElement.addEventListener('click', function() { 41 alert('documentElement click'); 42 }, false); 43 document.addEventListener('click', function() { 44 alert('document click'); 45 }, false); 46 // 移除事件处理moveEventListener 47 // p.s.事件处理函数只能调用相同的,哪怕写相同的匿名函数也不可以 48 btn1.removeEventListener('click', handler1, false); 49 </script> 50 </body> 51 52 </html>
事件兼容: IE兼容性问题
- 事件绑定:addEventListener与attachEvent
- 事件移除:removeEventListener与detachEvent
- 获取事件对象:e.target与 window.event.srcElement
- 阻止冒泡:e.stopPropagation与window.event.cancelBubble
- 阻止默认:e.preventDefault与window.event.returnValue
封装兼容事件后调用
1 var EventUtil = { 2 // 检测绑定事件 3 addHandler: function(element, type, handler) 4 // 传入事件元素,事件类型,执行程序 5 { 6 if (element.addEventListener) { 7 element.addEventListener(type, handler, false); 8 } 9 // ie浏览器 10 else if (element.attachEvent) { 11 element.attachEvent('on' + type, handler); // 在ie浏览器事件要加上on 12 } 13 // 都不行的话使用DOM0模型,直接脚本模式执行 14 else { 15 element['on' + type] = handler; 16 } 17 }, 18 removeHandler: function(element, type, handler) { 19 if (element.removeEventListener) { 20 element.removeEventListener(type, handler, false); 21 } else if (element.detachEvent) { 22 element.detachEvent('on' + type, handler); 23 } else { 24 element['on' + type] = null; 25 } 26 }, 27 // 获得事件 28 getEvent: function(event) { 29 if (event) { 30 return event; 31 } else { 32 return window.event; 33 } 34 // return event?event:window.event; 35 }, 36 // 获得Target 37 getTarget: function(event) { 38 return event.target || event.srcElement; 39 }, 40 // 取消默认行为 41 preventDefault: function(event) { 42 if (event.preventDefault) { 43 event.preventDefault(); 44 } else { 45 event.returnValue = false; 46 } 47 }, 48 // 取消冒泡 49 stopPropagation: function(event) { 50 if (event.stopPropagation) { 51 event.stopPropagation(); 52 } else { 53 event.cancelBubble = true; 54 } 55 }, 56 }
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <title></title> 6 <script type="text/javascript" src="EventUtil.js"></script> 7 </head> 8 9 <body> 10 <div id="box1" style="border:1px red solid;300px;height:100px"> 11 <input type="button" value="btn1" id="btn1"> 12 </div> 13 <a href="./EventUtil.js" id="a1">取消默认链接</a> 14 <script type="text/javascript"> 15 var btn1 = document.getElementById('btn1'); 16 17 function handler(e) { 18 // 获取事件 19 var e = EventUtil.getEvent(e); 20 console.log(e); 21 // 获取target,此处获取为btn1 22 var target = EventUtil.getTarget(e); 23 console.log(target); 24 console.log(target.tagName); 25 } 26 EventUtil.addHandler(btn1, 'click', handler); 27 28 document.onclick = function() { 29 console.log('document click'); 30 } 31 var box1 = document.getElementById('box1'); 32 box1.onclick = function(e) { 33 console.log('box1 click'); 34 // 取消冒泡 35 EventUtil.stopPropagation(e); 36 } 37 38 var a1 = document.getElementById('a1'); 39 a1.onclick = function(event) { 40 event = EventUtil.getEvent(event); 41 // 取消链接的默认行为 42 EventUtil.preventDefault(event); 43 }; 44 </script> 45 </body> 46 47 </html>