目录
事件对象
常见的事件对象举例👇
鼠标事件对象MouseEvent
// 获取事件对象
let box = document.querySelector(".box");
box.onclick = function (ev) {
console.log(ev);
}
- 属性:
- type: 事件类型
- target: 事件源
- clientX / clientY: 触发点距离窗口左上角坐标
- pageX / pageY: 触发点距离body左上角坐标
- …
- 方法: (基于原型链查找,在Event.prototype上)
- ev.preventDefault(): 阻止默认行为 兼容处理: ev.returnValue = false
- ev.stopPropagation(): 停止冒泡传播 兼容处理: ev.cancelBubble = true
- …
键盘事件对象KeyboardEvent
// 获取事件对象
document.onkeydown = function (ev) {
console.log(ev);
}
属性:keyCode / which: 键盘码
windows / mac 键盘码图👇
普通事件对象Event
// 获取事件对象
window.onload = function(ev){
console.log(ev);
}
手指事件对象TouchEvent——移动端
// 获取事件对象
box.ontouchstart = function(ev){
console.log(ev);
}
属性:
- touches: 只能获取到手指在屏幕上时的信息,手指离开信息就消失。
- changedTouches: 可获取到手指离开前的信息。结果是一个集合,一般通过
ev.changedTouches[0]
来获取第一个手指信息,里面存储了基本信息。
默认行为
默认行为举例:
- a标签的页面跳转 / 锚点定位
- 文本框输入内容
- 部分文本框的输入记忆
- 右键弹出右键菜单
- …
阻止默认行为:
// 阻止右键弹出菜单默认行为
window.oncontextmenu = function(ev){
ev.preventDefault();
}
// 阻止a标签的默认行为
// 方案一:
<a href="javascript:;" id="link">百度一下</a>
// 方案二:
<a href="www.baidu.com" id="link">百度一下</a>
<script>
link.onclick = function(ev){ // 点击a标签时先触发click事件再进行页面跳转
ev.preventDefault(); // 该操作会在触发点击事件时阻止默认行为,就不再进行后续的跳转了
}
</script>
事件的传播机制
事件传播分为三个阶段:
- 捕获阶段:外->里,直到找到当前触发的事件源为止,建立冒泡传播的路线。
- 目标阶段:当前元素相关事件行为触发,方法执行。
- 冒泡阶段:不仅当前元素相关事件行为触发,在捕获阶段获取的路线中所有相关事件的行为均被触发,从里向外依次执行相关的方法。
DOM0级事件绑定的方法均在目标阶段与冒泡阶段执行。
DOM2级事件绑定方法可以控制在捕获阶段执行,元素.addEventListener('xxx',xxx,false/true)
,默认为false(冒泡阶段执行),若设置为true,则在捕获阶段执行。(一般不用)
我们注意到,由于冒泡传播,点击center盒子从内到外依次触发了center、inner、outer、body上的相关事件。得到了“四个”MouseEvent。这“四个”MouseEvent实际上是同一个事件对象,因为只点击了一次。
事件对象用来记录当前操作的相关信息,与在哪个方法中没有关系;除非重新操作,那么存储的之前的操作信息会被最新操作信息覆盖。因此如果一次操作执行了多个方法,那么这些方法中的事件对象是同一个事件对象。
如果我们想阻止冒泡传播,使用ev.stopPropagation()
方法。
两对傻傻分不清楚的鼠标事件:
- mouseover & mouseout:鼠标移入和移出
- mouseenter & mouseleave:鼠标进入和离开
到底有啥区别?先给你个机会直观感受一下:
同样都是从上划到下,mouseover & mouseout竟然触发了八个事件,而mouseenter & mouseleave只触发了四个?
mouseover & mouseout:鼠标移入和移出,鼠标在元素上即over,不在即out;存在冒泡传播机制。
mouseenter & mouseleave:鼠标进入和离开,默认阻止了冒泡传播。从大盒子移动到内部的小盒子(实际没有从大盒子离开),再从小盒子移回大盒子(实际也没有重新进入大盒子,因为一直都在里面)。