事件对象和事件委托
一、事件对象的公共属性和方法
1. 公共属性
事件对象.target 获取最先触发的元素
this指向事件源,target指向最先触发的元素,即冒泡事件中的目标元素
子孙元素可以共享上级元素的事件
2. 公共方法
1)事件对象.preventDefault(); 阻止默认行为
在a标签中 href="javascript:"。
或在script代码最后加 return:false(推荐,无兼容性问题)。
或:e.preventDefault();(有兼容性问题)。
1 <script> 2 var a = document.querySelector('a'); 3 a.onclick = function(e) { 4 alert('hello'); 5 e.preventDefault(); 6 }; 7 </script>
2)事件对象.stopPropagation(); 停止冒泡传播
1 <script> 2 var divs = document.querySelectorAll('div'); 3 for(var i = 0; i < divs.length; i++) { 4 divs[i].onclick = function(e) { 5 alert(this.className); 6 e.stopPropagation(); 7 } 8 } 9 </script>
二、事件委托
从性能角度:函数也是一种数据类型,也需要存储在内存中。所以注册的事件越多,开辟的内存空间越多。浏览器在注册事件时也是耗时的, 注册的事件越多耗时越长。
从动态操作元素角度:动态添加的元素需要重新注册事件。
1. 事件委托
只需要注册一个事件就可以,不管是原有的子孙元素,还是未来动态添加的子孙元素,都可以实现功能。
2. 事件委托的实现
把子孙元素的事件委托给上级元素。
1)获取上级元素,给上级元素注册事件。
2)通过事件对象的target,获取最先触发的元素
3)可以选择使用nodeName检测是否是指定的元素
1 <script> 2 var ul = document.querySelector('ul'); 3 ul.onclick = function(e) { 4 if(e.target.nodeName == 'LI') { 5 alert(e.target.innerText); 6 } 7 }; 8 </script>
4)可以选择类名className检测是否为指定元素
1 <body> 2 <button>添加</button> 3 <div class="list"> 4 <h3>标题1</h3> 5 <h3 class="box">标题2</h3> 6 <h3>标题3</h3> 7 <p class="box">段落1</p> 8 <p>段落2</p> 9 <p>段落3</p> 10 <p class="box">段落4</p> 11 </div> 12 <script> 13 var div = document.querySelector('div'); 14 div.onclick = function (e) { 15 var t = e.target; 16 if(t.className == 'box'){ 17 alert(t.innerText); 18 } 19 } 20 </script> 21 </body>
3. 扩展:事件对象兼容性问题
事件对象:事件处理的第一个形参,是标准的。形参相当于一个变量。
在IE8中 console.log(e) 获取不到对象,返回 undefined; 可以用 window.event
方法1:
1 <script> 2 document.onclick = function (e) { 3 var _e; 4 if (e != undefined) { 5 _e = e; 6 } 7 else { 8 _e = window.event; 9 } 10 //IE低版本获取事件对象:widow.event; 11 // console.log(window.event); 12 console.log(_e); 13 } 14 </script>
方法2:
1 <script> 2 document.onclick = function (e) { 3 var _e = e || window.event; //返回为true的值 4 console.log(_e); 5 } 6 </script>
任何数据都可以参与任何运算。
左侧数据 || 右侧数据:若左侧数据能转换为布尔值且值为true时,就输出左侧数据,否则输出右侧数据。
左侧数据 && 右侧数据:若左侧数据能转换为布尔值且值为false时,输出左侧数据,否则输出右侧数据。
1&&2 //返回2
0&&2 //返回0