事件监听
- 什么是事件
- 什么是事件监听?
- 事件监听三要素
- 事件监听
- L0 绑定
- L2 绑定
- 区别
- vue绑定
- 事件类型
- 鼠标事件
- 键盘事件
- 焦点事件
- 文本事件
- 什么是事件对象
- 获取事件对象
- 环境对象
- 回调函数
- 事件流
- 事件捕获
- 事件冒泡
- 阻止冒泡
- 解绑事件
- 两种注册事件的区别
- 事件委托
什么是事件
- 事件是在编程时系统内发生的动作或者发生的事情
- 比如用户在网页上单击一个按钮
什么是事件监听?
- 就是让程序检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称为 绑定事件或者注册事
件 - 比如鼠标经过显示下拉菜单,比如点击可以播放轮播图等等
事件监听三要素
- 事件源: 那个dom元素被事件触发了,要获取dom元素
- 事件类型: 用什么方式触发,比如鼠标单击 click、鼠标经过 mouseover 等
- 事件调用的函数: 要做什么事
事件监听
L0 绑定
语法:元素对象.on事件 = function() { }
<button>点击</button>
const btn = document.querySelector('button')
btn.onclick = function(){
alert('点击')
}
L2 绑定
语法:元素对象.addEventListener(‘事件类型’,要执行的函数)
<button>点击</button>
// 需求: 点击了按钮,弹出一个对话框
// 1. 事件源 按钮
// 2.事件类型 点击鼠标 click 字符串
// 3. 事件处理程序 弹出对话框
const btn = document.querySelector('button')
btn.addEventListener('click', function () {
alert('你早呀~')
})
区别
on方式会被覆盖,addEventListener方式可绑定多次,拥有事件更多特性,推荐使用
vue绑定
<button onclick="hi()">点击</button>
function hi(){
alert('你好呀~')
}
事件类型
鼠标事件
鼠标出发
类型 | 触发 |
---|---|
click | 鼠标点击 |
mouseenter | 鼠标经过 |
mouseleave | 鼠标离开 |
dblclick | 鼠标双击 |
键盘事件
键盘触发
类型 | 触发 |
---|---|
keydown | 键盘按下触发 |
keyup | 键盘抬起触发 |
焦点事件
表单获得光标
类型 | 触发 |
---|---|
focus | 获得焦点 |
blur | 失去焦点 |
文本事件
表单输入触发
类型 | 触发 |
---|---|
input | 用户输入事件 |
什么是事件对象
- 也是个对象,这个对象里有事件触发时的相关信息
- 例如:鼠标点击事件中,事件对象就存了鼠标点在哪个位置等信息
- 使用场景
- 可以判断用户按下哪个键,比如按下回车键可以发布新闻
- 可以判断鼠标点击了哪个元素,从而做相应的操作
获取事件对象
在事件绑定的回调函数的第一个参数就是事件对象
一般命名为event、ev、e
语法:元素.addEventListener(‘事件类型’,function(e){})
input type="text">
const input = document.querySelector('input')
input.addEventListener('keyup', function (e) {
// console.log(e.key)
if (e.key === 'Enter') {
console.log('我按下了回车键')
}
})
环境对象
指的是函数内部特殊的变量 this ,它代表着当前函数运行时所处的环境
作用:弄清楚this的指向,可以让我们代码更简洁
- 函数的调用方式不同,this 指代的对象也不同
- 【谁调用, this 就是谁】 是判断 this 指向的粗略规则
- 直接调用函数,其实相当于是 window.函数,所以 this 指代 window
<button>点击</button>
// 每个函数里面都有this 环境对象 普通函数里面this指向的是window
// function fn() {
// 指向windo
// console.log(this)
// }
// window.fn()
const btn = document.querySelector('button')
btn.addEventListener('click', function () {
// console.log(this) // btn 对象
// btn.style.color = 'red'
this.style.color = 'red'
})
回调函数
如果将函数 A 做为参数传递给函数 B 时,我们称函数 A 为回调函数
简单理解: 当一个函数当做参数来传递给另外一个函数的时候,这个函数就是回调函数
//function函数就是回调函数
btn.addEventListener('click', function () {
alert(11)
})
事件流
事件流指的是事件完整执行过程中的流动路径
- 说明:假设页面里有个div,当触发事件时,会经历两个阶段,分别是捕获阶段、冒泡阶段
- 简单来说:捕获阶段是 从父到子 冒泡阶段是从子到父
- 实际工作都是使用事件冒泡为主
事件捕获
从DOM的根元素开始去执行对应的事件 (从外到里)
事件捕获需要写对应代码才能看到效果
语法:DOM.AddEventListener(‘事件类型’,事件处理函数,是否使用捕获机制)
说明:
- addEventListener第三个参数传入 true 代表是捕获阶段触发(很少使用)
- 若传入false代表冒泡阶段触发,默认就是false
- 若是用L0 事件监听,则只有冒泡阶段,没有捕获
<div class="father">
<div class="son"></div>
</div>
const fa = document.querySelector('.father')
const son = document.querySelector('.son')
// 输出:爷爷-爸爸-儿子,从大目标到小目标全部查找
document.addEventListener('click', function () {
alert('爷爷')
}, true)
fa.addEventListener('click', function () {
alert('爸爸')
}, true)
son.addEventListener('click', function () {
alert('儿子')
}, true)
事件冒泡
当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称为事件冒
泡
- 简单理解:当一个元素触发事件后,会依次向上调用所有父级元素的 同名事件
- 事件冒泡是默认存在的
- L2事件监听第三个参数是 false,或者默认都是冒泡
阻止冒泡
问题:因为默认就有冒泡模式的存在,所以容易导致事件影响到父级元素
需求:若想把事件就限制在当前元素内,就需要阻止事件冒泡
前提:阻止事件冒泡需要拿到事件对象
语法:事件对象.stopPropagation()
注意:此方法可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效
<div class="father">
<div class="son"></div>
</div>
const fa = document.querySelector('.father')
const son = document.querySelector('.son')
// 输出:儿子-爸爸-爷爷,从小目标到大目标
document.addEventListener('click', function () {
alert('爷爷')
})
fa.addEventListener('click', function () {
alert('爸爸')
})
son.addEventListener('click', function (e) {
alert('儿子')
// 阻止冒泡 事件对象.stopPropagation()
// 点击儿子时,只输出儿子,不会向上输出
//e.stopPropagation()
})
解绑事件
- on事件方式
直接使用null覆盖偶就可以实现事件的解绑
语法:对象.onclick = null
// L0 绑定事件
btn.onclick = function(){
alert('点击')
}
//解绑事件
btn.onclick = null
- addEventListener方式
语法:removeEventListener(事件类型, 事件处理函数, [获取捕获或者冒泡阶段])
注意:匿名函数无法被解绑
function fn() {
alert('点击')
}
// L2 事件绑定
btn.addEventListener('click', fn)
// L2 事件移除解绑
btn.removeEventListener('click', fn)
两种注册事件的区别
- 传统on注册(L0)
- 同一个对象,后面注册的事件会覆盖前面注册(同一个事件)
- 直接使用null覆盖偶就可以实现事件的解绑
- 都是冒泡阶段执行的
- 事件监听注册(L2)
- 语法: addEventListener(事件类型, 事件处理函数, 是否使用捕获)
- 后面注册的事件不会覆盖前面注册的事件(同一个事件)
- 可以通过第三个参数去确定是在冒泡或者捕获阶段执行
- 必须使用removeEventListener(事件类型, 事件处理函数, 获取捕获或者冒泡阶段)
- 匿名函数无法被解绑
事件委托
事件委托是利用事件流的特征解决一些开发需求的知识技巧
优点:减少注册次数,可以提高程序性能
原理:事件委托其实是利用事件冒泡的特点,给父元素注册事件,当我们触发子元素的时候,会冒泡到父元素身上,从而触发父元素的事件
ul父元素 li 子元素 点击事件
ul.addEventListener(‘click’, function(){}) 点击li子元素执行ul父级点击事件
语法:事件对象.target.tagName 可以获得真正触发事件的元素
<ul>
<li>第1个孩子</li>
<li>第2个孩子</li>
<li>第3个孩子</li>
<li>第4个孩子</li>
<li>第5个孩子</li>
<p>我不需要变色</p>
</ul>
// 需求:点击每个小li 当前li 文字变为红色
// 按照事件委托的方式 委托给父级,事件写到父级身上
// 获得父元素
const ul = document.querySelector('ul')
ul.addEventListener('click', function (e) {
// console.dir(e.target) // 就是我们点击的那个对象
// e.target.style.color = 'red'
// 我们只要点击li才会有效果,e.target.tagName获取当前触发元素名
if (e.target.tagName === 'LI') {
e.target.style.color = 'red'
}
})