事件
# 事件级别
事件级别又分 DOM0 级、DOM2 级、DOM3 级。
DOM0级事件:1. 直接在标签内直接添加执行语句,2. 定义执行函数
<input type="text" id="test">
<input type="button" value="button" onclick="alert(document.getElementById('test').value)">
<script>
document.getElementById('button').onclick=function(){
alert(document.getElementById('test').value);
}
</script>
2
3
4
5
6
7
8
DOM2 级事件:addEventListener
element.addEventListener('click',function(){},false)
DOM3 级事件:给 addEventListener 新增了更多事件类型,如鼠标事件、键盘事件等。
element.addEventListener('keyup',function(){},false)
# 事件流
# 事件冒泡
自下而上
事件冒泡:从目标元素开始,往顶层元素传播。途中如果有节点绑定了相应的事件处理函数,这些函数都会被一次触发。
# 阻止事件冒泡
e.stopPropagation()
# 阻止节点绑定的其他事件
e.stopImmediatePropagation()
# 应用场景
实现事件代理
如果父或子元素同时绑定了事件,在执行子元素事件是不想触发父元素,那么子元素的事件需要停止冒泡,event.stopPropagation()
如果 li 内还包含有其他元素,那么点击时得到的event.target就不是 li 标签,就需要用到冒泡一级一级往上找,直到找到这个 li 标签才触发
# 事件捕获
自上而下
事件捕获:从顶层对象 document 发出一个事件流,随着DOM树的节点向目标元素节点流去,直到到达事件真正发生的目标元素。在这个过程中,事件相应的监听函数是不会被触发的。
# 实现事件捕获
addEventListener(event, fn, true/false)
: 第三参数默认是false(冒泡),true(捕获)。
<div id="first">
<button id="button">事件冒泡</button>
</div>
<script>
// 结果:先执行first的事件,再执行button
document.getElementById("button").addEventListener("click",function(){
alert("button");
},true);
document.getElementById("first").addEventListener("click",function(){
alert("first");
},true);
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 阻止事件捕获
- 阻止捕获,只要阻止事件执行,就可以阻止捕获,所以使用 stopPropagation() 也可以阻止捕获
# 事件监听
事件处理程序/事件监听的名字以on
开头,因此 click 事件的事件处理程序就是 onclick,load 事件的事件处理程序就是 onload。
# html 事件
<input type="button" value="click" onclick="showMsg()">
# 添加/删除事件
- 添加:
addEventListener(event, fnName, true/false)
第三个参数为 true,表示在捕获阶段调用,false 则是在冒泡阶段调用 - 删除:
removeEventListener(event, fnName, true/false)
所有的 dom 节点都包含这两个方法。
addEventListener() removeEventListener() 属于Dom2 级事件处理程序
var btn = document.getElementById('myBtn');
btn.addEventListener("click", function() {
console.log('点击了')
}, false);
2
3
4
注意点:
- addEventListener 是可以添加多个的
- addEventListener 后只能用 removeEventListener 移除,并且使用完后要记得移除,否则会占用内存
- 最好加在冒泡阶段,也就是第三个参数不设置为 true,兼容型比较好
# 事件对象
在触发 Dom 的某个事件时,会产生一个事件对象 event,这个对象中包含所有与事件有关的信息。
每个 event 对象都有以下属性和方法,并且它们都是只读的。
属性/方法 | 类型 | 说明 |
---|---|---|
bubbles | Boolean | 表明事件是否冒泡 |
cancelable | Boolean | 表明是否可以取消事件的默认行为 |
currentTarget | Element | 其事件处理程序当前正在处理事件的那个元素 |
target | Element | 事件的目标 |
defaultPrevented | Boolean | 为 true 表示已经调用了 preventDefault()(DOM3级事件中新增) |
detail | Integer | 与事件相关的细节信息 |
eventPhase | Integer | 调用事件处理程序的阶段:1 表示捕获阶段,2 表示“处于目标”,3 表示冒泡阶段 |
type | String | 被触发的事件的类型 |
view | AbstractView | 与事件关联的抽象视图。等同于发生事件的window对象 |
preventDefault() | Function | 取消事件的默认行为。如果cancelable是true,则可以使用这个方法 |
stopImmediatePropagation() | Function | 取消事件的进一步捕获或冒泡,同时阻止任何事件处理程序被调用(DOM3级事件中新增) |
stopPropagation() | Element | 取消事件的进一步捕获或冒泡。如果bubbles为true,则可以使用这个方法 |
在事件处理程序内部,对象 this 始终等于 currentTarget 的值,而 target 则只包含事件的实际目标。如果直接将事件处理程序指定给了目标元素,则 this、currentTarget 和 target 包含相同的值。
# 事件委托/事件代理
例如一个列表中的每一个元素都需要一个点击效果,不需要每一个都绑定 click 事件,可以将事件委托给父级元素来触发,也就是事件委托。
事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
事件委托通过 addEventListener
实现。
<ul id="list">
<li data-value="1">1111</li>
<li data-value="2">2222</li>
<li data-value="3">3333</li>
<li data-value="4">4444</li>
</ul>
<script>
var list = document.getElementById('list')
list.addEventListener('click', function(event) {
console.log('event', event.target) // 对应li
})
</script>
2
3
4
5
6
7
8
9
10
11
12
# 事件类型
详细事件类型 - 《MDN - 事件参考》