目录
1.事件对象
1.1获取事件对象
1.2事件对象常用属性
2.事件流
1.1事件流的两个阶段:冒泡和捕获
1.2阻止事件流动
1.3阻止默认行为
1.4两种注册事件的区别
3.事件委托
1.事件对象
1.1获取事件对象
事件对象:也是一个对象,这个对象里有事件触发时的相关信息
例如:鼠标点击事件中,事件对象就存了鼠标点在哪个位置的信息
获取事件对象:
- 在事件绑定的回调函数的第一个参数就是事件对象
- 一般命名为event,ev,e
语法:元素.addEventListener('click', function(e) { }) e就是事件对象
1.2事件对象常用属性
常用属性
- type:获取当前事件类型
- clientX/clientY:获取光标相对于浏览器可见窗口左上角的位置
- pageX/pageY:获取光标相对于浏览器窗口左上角的位置
- offsetX/offsetY:获取光标相对于当前DOM元素左上角的位置
- key:用户按下的键盘键的值(现在不再使用keyNode)
案例:图片跟随鼠标
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>img {position: absolute;top: 0;left: 0;}</style>
</head>
<body><img src="./pictures/tianshi.gif" alt=""><script>let img = document.querySelector('img')document.addEventListener('mousemove', function(e) {// 鼠标坐标赋值给图片// 减值是为了让鼠标在图片上面img.style.left = e.pageX - 50 + 'px'img.style.top = e.pageY - 40 + 'px'})</script>
</body>
</html>
2.事件流
1.1事件流的两个阶段:冒泡和捕获
事件流:事件完整执行过程中的流动路径
假设页面里有一个div,当触发事件时,会经历两个阶段:捕获阶段和冒泡阶段
①事件冒泡:
当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发(依次向上调用所有父级元素的同名事件),这一过程称为事件冒泡
📖Note:
- 事件冒泡是默认存在的
②事件捕获:
从DOM的根元素开始去执行对应的事件(从外到里)
📖Note:
- 事件捕获需要写对应的代码才能看到
- DOM.addEventListener(事件类型,事件处理函数,是否使用捕获机制),第三个参数传入true代表是捕获阶段触发(不常用),传入false代表冒泡阶段触发,默认false
- 若是用L0事件监听,则只有冒泡阶段,没有捕获阶段
捕获:父级到子级 冒泡:子级到父级
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.grand {margin: 100px;width: 500px;height: 500px;background-color: red;}.father {width: 400px;height: 400px;background-color: pink;}.son {width: 200px;height: 200px;background-color: skyblue;}</style>
</head>
<body><div class="grand"><div class="father"><div class="son"></div></div></div><script>let grand = document.querySelector('.grand')let father = document.querySelector('.father')let son = document.querySelector('.son')grand.addEventListener('click', function(e) {alert('爷爷级元素的点击事件')})father.addEventListener('click', function() {alert('父级元素的点击事件')})son.addEventListener('click', function() {alert('子级元素的点击事件')})</script>
</body>
</html>
上面的案例中,当点击子级元素时,先触发子级元素的绑定的点击事件,再依次向上触发父级元素绑定的点击事件,依次类推,直到访问完所有的父级元素,这个过程即为事件冒泡
事件捕获的过程同理:只不过是从根元素向下访问所有的子级元素
1.2阻止事件流动
冒泡模式默认存在,可能会导致事件影响到父级元素;若想把事件限制在当前元素内,就要阻止事件流动
语法:时间对象.stopPropagation()
📖Note:
- 阻止事件流动需要拿到事件对象,因此回调函数的形参列表必须写e/event
上面的案例中:组织事件流动后,当点击子级元素时,只触发子级元素的点击事件,不会触发父级元素的点击事件
📖Note:鼠标经过事件
- mouseover和mouseout会有冒泡效果
- mouseenter和mouseleave没有冒泡效果(推荐)
1.3阻止默认行为
默认行为,比如链接点击不跳转,表单域的跳转
语法:e.preventDefault()
1.4两种注册事件的区别
两种注册事件的区别:
传统on注册(L0)
- 同一个对象,后面注册的事件会覆盖前面注册(同一个事件)
- 直接使用null覆盖偶就可以实现事件的解绑
- 都是冒泡阶段执行的
事件监听注册(L2)
- 语法: addEventListener(事件类型, 事件处理函数, 是否使用捕获)、
- 后面注册的事件不会覆盖前面注册的事件(同一个事件)
- 可以通过第三个参数去确定是在冒泡或者捕获阶段执行
- 必须使用removeEventListener(事件类型, 事件处理函数, 获取捕获或者冒泡阶段)
- 匿名函数无法被解绑
3.事件委托
利用事件流的特征解决一些开发需求
场景:多个子级元素进行同样的操作时,可以将这个操作委托给父级元素;比如所有的子级元素都要绑定点击事件,则可以给它们的父级添加点击事件,由于冒泡模式默认存在,所以当自身没有绑定点击事件时,会触发父级的点击事件
获取点击的对象,语法:e.target
获取点击的对象的名字,语法:e.target.tagName