一、事件对象
什么是事件对象
当触发一个事件以后,对该事件的一些描述信息
比如:
鼠标点击时的坐标
触发键盘事件时按下的那个按键
每一个事件都会有一个对象来描述这些信息,我们就把这个对象叫做事件对象
浏览器给我们一个“黑盒子”,叫做 window.event 就是对事件信息的所有描述
语法:
元素.onclick = function(){
console.log(window.event.X轴的坐标点信息)
console.log(window.event.Y轴的坐标点信息)
}
缺点:这个东西有兼容性问题,在低版本的IE里边能用,但是在高版本 IE和 Chrome里面不好使
所以我们需要换一种使用方式:
就是在一个事件处理函数的形参位置,默认第一个就是事件对象
二、点击事件的光标位置
坐标一定是一个相对的数据
比如:
- 相对于事件源(就是我们点击的那个元素)
- 相对于页面
- 相对于浏览器窗口
<html>
<head>
<style>
body{
height: 5000px;
}
div{
width: 300px;
height: 300px;
padding: 20px;
border: 10px solid #333;
margin: 50px;
position: fixed;
top: 50px;
}
</style>
</head>
<body>
<div></div>
<script>
// 0.获取元素
var box = document.querySelector('div')
box.onclick = function(e){
// 1.相对于事件源的鼠标坐标点 相对于点击的元素的边框内侧开始计算
console.log('相对于事件源 X轴', e.offsetX)
console.log('相对于事件源 Y轴', e.offsetY)
// 2.相对于页面
console.log('==========分割线==========')
console.log('相对于页面 X 轴', e.pageX)
console.log('相对于页面 Y 轴', e.pageY)
// 3.相对于浏览器窗口
console.log('==========分割线==========')
console.log('相对于浏览器窗口 X 轴', e.clientX)
console.log('相对于浏览器窗口 Y 轴', e.clientY)
}
</script>
</body>
三、获取键盘按键
键盘的每一个按键都有一个自己的编码,我们可以通过 事件对象.keyCode 来获取
<body>
<input type="text">
<script>
// 0. 获取元素
var inp = document.querySelector('input')
// inp.onkeyup = function (e) {
// console.log('e.keyCode:' + e.keyCode + ';e.key:' + e.key)
// }
/**
* 组合按键 alt / shift / ctrl
*/
inp.onkeyup = function (e) {
// console.log(e.ctrlKey)
// console.log(e.altKey)
// console.log(e.keyCode) //q===81
if (e.altKey && e.keyCode === 81) {
console.log('按下了组合按键 alt + q')
}
}
</script>
</body>
四、onXXX绑定的弊端
<html>
<head>
<style>
div {
width: 200px;
height: 200px;
background-color: pink;
}
</style>
</head>
<body>
<div></div>
<script>
// 0. 获取元素
var box = document.querySelector('div')
// 1. 给box元素添加一个点击事件
box.onclick = function () {
console.log('点击事件1,触发了~')
}
// 2. 给box元素添加第二个点击事件
box.onclick = function () {
console.log('点击事件2,触发了~')
}
/**
* 问题:
* 我们现在注册事件就是通过 onXXX
* 只能给元素注册一个事件,如果写了第二个,那么第一个就会被覆盖掉
*
* 解决:
* 如果想要两个事件全都存在,我们可以使用事件监听的方式去给元素绑定事件
*
* 使用 addEventListener 去给元素通过事件监听的方式
* 在IE中需要使用 attachEvent (了解即可)
*/
</script>
</body>
</html>
五、事件监听
addEventListener
-
语法:元素.addEventListener('事件类型',事件处理函数,第三个形参)
-
第三个形参先欠着,后续会详细讲解
-
因为有默认值,我们暂时先不传递第三个形参
-
注意:这里的事件类型全部都一样,不需要加 on
-
执行顺序:按照我们注册的顺序执行(也就是代码书写的顺序)
<html>
<head>
<style>
div {
width: 200px;
height: 200px;
background-color: pink;
}
</style>
</head>
<body>
<div></div>
<script>
// 0. 获取元素
var box = document.querySelector('div')
// 元素.addEventListener('事件类型',事件处理函数,第三个形参)
box.addEventListener('click', function () {
console.log('绑定的第一个事件')
})
box.addEventListener('click', function () {
console.log('绑定的第二个事件')
})
box.addEventListener('click', function () {
console.log('绑定的第三个事件')
})
</script>
</body>
</html>
六、事件传播
假设我们在浏览器内用一个宽高500px的盒子,内部有一个水平垂直都居中的子级盒子,宽高为100px
当我点击在子级盒子上的时候,其实也是点击在了这个父级盒子的身上
这种情况就叫做事件传播
当元素触发一个事件的时候,这个元素的父级节点也会触发相同的事件,父元素的父元素也会触发相同的事件
-
点击了子级盒子,会触发子级盒子的点击事件
-
也是点在了父级盒子上,也会触发父级盒子的点击事件
-
也是点在了 body 上,也会触发 body 的点击事件
-
也是点在了 html 上,也会触发 html 的点击事件
-
也是点在了 document 上,也会触发 document 的点击事件
-
也是点在了 window 上,也会触发 window 的点击事件
-
页面上任何一个元素触发事件,都会一层一层的最终导致window的相同事件触发
-
前提是一定得有事件
注意点:
1.只会传播同类事件,如果是点击事件,那么只会触发父级或者父级的父级注册的点击事件,其他类型的事件不会触发
2.只会从点击的元素开始,按照html的结果,逐层向上触发同类型的事件
3.内部元素不管有没有该事件,只要上层元素有该事件,那么上层元素的事件就会触发
七、事件的冒泡与捕获与目标
目标
你点击在哪个元素上,那么这个事件的目标就是这个元素
事件的冒泡与捕获(面试题)
冒泡:就是从目标的事件处理函数开始,依次向上,一直到window的事件处理函数触发
也就是说从下向上的执行事件处理函数
捕获:就是从window的事件处理函数开始,依次向下,一直到目标的事件处理函数触发
也就是说从上向下的执行事件处理函数
按照事件捕获的形式传播
addEventListener 第三个参数就是决定当前传播方式为捕获还是冒泡
默认第三个参数为false,代表传播方式为冒泡
如果想按照捕获的形式传播,那么给第三个参数传递一个true
区别:就是在事件的传播中,多个同类型的事件处理函数的执行顺序不同,仅此而已
八、事件委托
事件委托,就是要把我自己做的事,委托给别人帮我完成
因为我们的冒泡机制,点击子元素的时候,也会同步触发父元素的相同事件
所以我们可以把子元素的事件委托给父元素来做
点击子元素的时候,不管子元素有没有点击事件,只要父元素有点击事件,那么就可以触发父元素的点击事件
事件委托的优点
* 页面上本身没有li,通过代码添加了一些li
* 这些li是没有点击事件的,每次动态的添加li,还需要重新给li绑定一次点击事件
* 这时候使用事件委托就比较合适
* 因为:新加进来的li也是ul的子元素,点击的时候也可以触发 ul的点击事件
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
</body>
九、默认行为
默认行为:不用我们注册,但是自己存在的事情
比如:
-
鼠标右键单击,会弹出一个菜单
-
点击a标签后,自己会跳转到页面
这些不需要我们注册就能实现的事情,我们叫做默认事件
阻止默认事件
不希望浏览器执行默认事件时,比如点击a标签,不跳转页面,那么就需要阻止默认事件
两种方式:
1.e.preventDefault() --- 非IE浏览器
2.e.returnValue = false --- IE浏览器(了解即可)
<body>
<a href="https://www.baidu.com/">点击之后跳转百度</a>
<script>
var oA = document.querySelector('a')
oA.onclick = function (e) {
console.log('该函数执行,拦截掉了 a 标签的默认行为')
e.preventDefault()
}
</script>
</body>