事件绑定
什么是事件?
- JS 中的事件就是对用户特定的行为作出相应的响应的过程
- 即浏览器监听到用户某些行为的时候,会执行对应的绑定程序
- 每个事件都应该有自己的载体
什么是事件的绑定?
- 在 html 元素上将触发事件的行为和事件的相应的程序关联起来的过程就是事件的绑定
传统事件绑定和符合W3C标准的事件绑定有什么区别?
1. 传统事件绑定:
<div onclick="">123</div>
div1.onclick = function(){};
<button onmouseover=""></button>
注意:
如果给同一个元素绑定了两次或多次相同类型的事件,那么绑定会被覆盖
2. 符合W3C标准的事件绑定的方式 addEventListener/attachEvent
addEventListener / removeEventListener
兼容:firefox、chrome、IE、safari、opera;不兼容IE7、IE8
let box = document.querySelector('.box') // 获取dom元素
function fun1(){console.log('box clicked...')} // 事件函数
box.addEventListener('click',fun1) //绑定事件
box.removeEventListener('click',fun1) //移除事件
所有的DOM节点都包含这两个方法,并且他们都接受三个参数:
- 事件类型
- 事件处理方法
- 布尔参数,默认false (true:捕获阶段调用事件处理方法;false:冒泡阶段调用事件处理方法。)
注意:
- 如果给同一个元素绑定了两次或多次相同类型的事件,绑定依次触发
- 支持DOM事件流
- 进行事件绑定不需要
on
前缀
attachEvent / detachEvent
兼容:IE7、IE8;不兼容firefox、chrome、IE9、IE10、IE11、safari、opera
// IE只支持事件冒泡
let box = document.querySelector('.box')
function fun1(){console.log('box clicked...')}
box.attachEvent('onclick',fun1) // 绑定事件
box.detachEvent('onclick',fun1) // 移除事件
这两个方法都接受两个相同的参数:
- 事件处理程序名称
- 事件处理程序方法
注意:
- 进行事件类型传参需要带上
on
前缀 - 这种方式只支持事件冒泡,不支持事件捕获
事件冒泡与捕获
事件冒泡
由点击的div
一层一层往上触发事件
<div id="box1">
<div id="box2">
<div id="box3">
点击触发事件
</div>
</div>
</div>
let box1 = document.getElementById('box1');
let box2 = document.getElementById('box2');
let box3 = document.getElementById('box3');
box1.addEventListener('click',function(){
console.log('box1');
},false);
box2.addEventListener('click',function(){
console.log('box2');
},false);
box3.addEventListener('click',function(){
console.log('box3');
},false);
// 事件冒泡输出:
// box3
// box2
// box1
事件捕获
与事件冒泡相反,由最外面的div
一层一层往下触发事件
<div id="box1">
<div id="box2">
<div id="box3">
点击触发事件
</div>
</div>
</div>
let box1 = document.getElementById('box1');
let box2 = document.getElementById('box2');
let box3 = document.getElementById('box3');
box1.addEventListener('click',function(){
console.log('box1');
},true);
box2.addEventListener('click',function(){
console.log('box2');
},true);
box3.addEventListener('click',function(){
console.log('box3');
},true);
// 事件捕获输出:
// box1
// box2
// box3
如何阻止事件冒泡和默认事件?
-
防止冒泡和捕获
w3c的方法是e.stopPropagation()
,IE则是使用e.cancelBubble = true
-
取消默认事件
w3c的方法是e.preventDefault()
,IE则是使用e.returnValue = false
事件代理(委托)
利用事件冒泡的原理,让自己的所触发的事件,让他的父元素代替执行
- js中事件冒泡我们知道,子元素身上的事件会冒泡到父元素身上。
- 事件代理就是,本来加在子元素身上的事件,加在了其父级身上。
- 那就产生了问题:父级那么多子元素,怎么区分事件本应该是哪个子元素的?
- 答案是:
event对象
里有记录的“事件源”,它就是发生事件的子元素。 - 它存在兼容性问题,在老的IE下,事件源是
window.event.srcElement
,其他浏览器是event.target
用事件代理有什么好处呢?
- 第一个好处是效率高,比如:不用
for循环
为子元素添加事件了 - 第二个好处是,
js
新生成的子元素也不用新为其添加事件了,程序逻辑上比较方便
代码示例:
<ul id="ul">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
var ul = document.getElementById('ul');
ul.onmouseover = function(e){
var e = e || window.event;
var li = e.srcElement || e.target;
// toLowerCase() 转换为小写
if(li.nodeName.toLowerCase() == 'li'){ // 事件源的nodeName 判断是不是li
li.style.background = 'red';
}
}
ul.onmouseout = function(e){
var e = e || window.event;
var li = e.srcElement || e.target;
if(li.nodeName.toLowerCase() == 'li'){ // 事件源的nodeName 判断是不是li
li.style.background = '';
}
}
效果图: