事件
了解事件
什么是事件?
- 我们使用代码的方式和某个内容约定好了一个行为
=》当你打开浏览器,触发了该行为的时候
=》会有对应的代码执行
事件三要素
- 事件源:和谁约定事件(和由谁触发不一样)
- 事件类型:约定了一个什么事件
- 事件处理函数:当行为发生的时候,需要执行的函数
- 三个内容的目的为了绑定事件、注册事件、提前做好约定
事件绑定
- DOM0 级事件
语法:事件源.on 事件类型 = 事件处理函数
注意:给一个事件源的同一事件类型,只能把绑定一个事件处理函数
let btn = document.querySelector("button");
btn.onclick = function () {
console.log(1);
};
btn.onclick = function () {
console.log(2);
};
// 代码结果:2
- DOM2 级事件(事件侦听器/事件监听器)
语法:事件源.addEventListener(‘事件类型’,事件处理函数)
特点:可以给同一个事件源的同一个事件类型绑定多个处理函数
// 2级
btn.addEventListener("click", function () {
console.log(1);
});
btn.addEventListener("click", function () {
console.log(2);
});
// 代码结果:1 2
事件解绑
- DOM 0
语法:事件源.on 事件类型 = null;
因为是赋值符号,当你给这个事件类型赋值为 null 时
会把本身的处理函数覆盖
当你再次出发行为的时候,没有事件处理函数执行
相当于解绑了事件
let btn = document.querySelector("button");
// 0级
btn.onclick = function () {
console.log(2);
};
// DOM 0级事件解绑
btn.onclick = null;
- DOM 2
语法:事件源.removeEventListener(“事件类型”,事件处理函数)
注意:
当你使用 DOM2 级事件解绑时
因为函数是一个复杂数据类型,所以你在绑定的时候
需要把函数单独写出来,以函数名的形式进行绑定和解绑
// 事件处理函数
function fn() {
console.log(2);
}
// 绑定事件
btn.addEventListener("click", fn);
// 解绑成功
btn.removeEventListener("click", fn);
// 解绑失败
btn.removeEventListener("click", function () {
console.log(2);
});
事件类型
注意:js 的原生事件没有大写字母
- 鼠标
- 键盘
- 浏览器
- 表单
- 触摸
- 其他
鼠标事件
- click:鼠标左键单击
- dblclick:鼠标左键双击
- contextmenu:鼠标右键单击
- mousedown:鼠标按下(任意按键按下)
- mouseup:鼠标抬起
- mousemove:鼠标移动
- mouseout:鼠标移出
- mouseover:鼠标移入
- mouseenter:鼠标移入
- mouseleave:鼠标移出
mouseout、mouseover 与 mouseenter、mouseleave 的区别
- 无论鼠标指针离开或进入被选元素还是其任何子元素,都会触发 mouseout、mouseover 事件
- 只有在鼠标指针离开或进入被选元素时,才会触发 mouseenter、mouseleave 事件。
键盘事件
- keydown 键盘按下触发
- 键盘上任何一个按键按下都能触发
- keyup 键盘抬起时触发
- 键盘上任何一个按钮抬起都能触发
- keypress 长按触发
- 必须按下可以真实键入内容的按键(delete/shift 等不能触发)
表单事件
- focus:聚焦事件
- blur:是去焦点事件
- change:改变事件
- 聚焦和失焦的时候,内容不一致,才会触发
- input:输入事件
- 只要表单输入内容或删除内容,就会实时触发
- reset:重置事件
- submit:提交事件
触摸事件
只能在移动端设备使用
- touchstart:触摸开始,表示手指接触到屏幕的瞬间
- touchmove:触摸移动。手指在屏幕上移动的时候
- touchend:触摸结束,手指离开屏幕的瞬间
index.html:136 [Violation] Added non-passive event listener to a scroll-blocking ‘touchstart’ event. Consider marking event handler as ‘passive’ to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
// 问题:;浏览器对e.preventDefault()的检测机制不一样了。
// 解决
box.addEventListener(
"touchstart",
function (e) {
console.log("我摸你了");
e.preventDefault();
},
{ passive: true }
);
// 添加passive属性,设为true,表示该事件内部不会使用e.preventDefault()来阻止浏览器的默认行为
// 如果这时代码中存在e.preventDefault()则会报错
// 设为false表示代码中存在e.preventDefault()。
// 当passive设为true表示(被动监听事件)
// 当passive设为false表示(非被动监听事件)
其他事件
- transitionend
- selectstart
- animationstart
- animationend
事件对象
是一个对象类型,记录了本次事件的所有信息
box.addEventListener("click",function(e){
// 这个函数是在你做出点击行为后,
// 被浏览器捕获了,之后就由浏览器去调用这个函数,
// 且定义了一个参数叫做e
// 因为是浏览器来调用,浏览器就会在调用这个函数的时候,
// 把它记录下来的所有和当前click事件相关的信息
// 赋值给形式参数e
e = e || window.event;
console.log(e); //PointerEvent {isTrusted: true, pointerId: 1, width: 1, height: 1, pressure: 0, …}
console.log(e.target);
})
事件对象信息 – 鼠标事件
- clientX 和 clientY
光标相对于浏览器可视窗口左上角的位置 - pageX 和 pageY
相对于文档流的左上角的坐标位置 - offsetX 和 offsetY
相对触发事件的元素左上角的坐标点
事件对象
事件对象信息 – 键盘事件
- 按下的是哪个按键
- 是否是组合按键
-
按下的是哪个按键
=》在事件对象中有一个信息叫做keycode(键的编码)
-》市场上的每一个计算机 每一个按键都被定义了一个编码,我们可以通过这个编码,来进行判断他点击的是哪个按键
=> 注意:
=》一个兼容问题
=》在标准浏览器下使用keyCode
=》在firefox < 20 的浏览器下使用 which -
组合按键
=》在事件对象内有四个信息
-》shiftKey
-》ctrlKey
-》altKey
-》metaKey
-》在win系统中表示 win键
-》在os系统中表示 command键
=》以上四个属性的值 都是布尔值
-》true 表示按下了
-》false 表示没按下
=》如果你想判断组合按键,主要在判断键盘编码时
-》额外判断一下以上四个属性就可以了
事件的传播(事件机制)
- 当一个事件在浏览器中触发的时候
- 不光在自身元素上触发,是会传播出去的
- 传播的是什么?传播的是事件的行为
概念:当你在一个元素上触发行为的时候,会按照父级结构的顺序,向上直到 window 传递该行为。
-
事件传播:当我打开页面 点击了son(我们看到的)
将点击在son身上的点击行为传播下去
注意:点击和点击行为是不一样的,传播的是点击行为,而我们的点击只是在son上点击了一下- 首先点击发生在son身上
- 因为事件传播,点击行为被传播了,点击行为也发生在了box身上
- 因为事件传播,点击行为被传播了,点击行为也发生在了body身上
- 因为事件传播,点击行为被传播了,点击行为也发生在了html身上
- 因为事件传播,点击行为被传播了,点击行为也发生在了document身上
- 因为事件传播,点击行为被传播了,点击行为也发生在了window身上
-
真实的传播
- 首先 window 接受到了行为,按照结构顺序逐层向下传递找到准确触发事件的元素
- 从准确触发事件的元素向上传递回window
- 在这个过程中,每一个内容都接受了两次行为,但是为什么事件处理函数只被调用了一次呢?
- 因为浏览器的事件执行机制
-
浏览器的事件执行机制
- 所有浏览器默认在 向上传递的 过程中触发事件处理函数
-
事件的三个阶段
- 捕获阶段:从window 向目标 传递的过程
- 目标阶段:事件发生在目标身上
- 冒泡阶段:从目标 向window传递的过程
let box = document.querySelector(".box");
let son = document.querySelector(".son");
box.onclick = function(){
console.log("我被执行了,我是box的事件处理函数");
}
document.body.onclick = function(){
console.log("body");
}
document.documentElement.onclick = function(){
console.log("html");
}
document.onclick = function(){
console.log("document");
}
window.onclick = function(){
console.log("window");
}
传递的是行为!!!!
传递的是行为!!!!
传递的是行为!!!!
冒泡和捕获
事件冒泡:在事件的传播过程中,从目标到window的过程
事件捕获:在事件的传播过程中,从window到目标的过程
事件目标:准确触发事件的那个元素
怎么拿? e.tagret
怎么在捕获时执行?
DOM0 级不行
DOM2 级可以,利用addEventListener 的第三参数来实现
- 默认时 false,表示冒泡阶段
- true,表示捕获阶段
阻止事件的传播
标准浏览器下使用
- e.stopPropagation();
IE低版本下使用
- e.cancelBubble = true
son.addEventListener("click", function (e) {
try {
// 首先执行try{}中的代码
// 如果代码没有报错,就不走catch
// 如果代码报错,就执行catch{}内的代码,并且会将报错信息放到catch里。通过一个变量接收。不会阻塞后续代码运行
e.stopPropagation();
} catch (error) {
// console.log(error);
e.cancelBubble = true
}
console.log("son");
});
阻止默认行为
- 不需要绑定事件,当你触发行为的时候,就会出现效果的事情
- 我们叫做默认行为
例子:
- a标签:点击之后跳转
- form标签的提交行为
-
标准浏览器
e.preventDefault() -
Ie低版本
e.returnValue = false; -
通用方法
return false
let a = document.querySelector("a");
let form = document.querySelector("form")
a.onclick = function(e){
console.log(111);
// e.preventDefault();
// return false;
// 兼容写法
try {
e.preventDefault();
} catch (error) {
e.returnValue = false;
}
// 简单粗暴
return false;
}
// tijiao.onclick = function(e){
// e.preventDefault();
// }
form.onsubmit = function(e){
e.preventDefault();
}
事件委托
- 原则:
- 尽可能找到距离最近的公共父级
- 尽可能找到页面上不动的元素来委托
/*
需求:
1.页面上有若干个li,点击每个li,控制台输出该li的文本内容
2.点击button 可以创建一个li出来
*/
let ul = document.querySelector("ul");
let btn = document.querySelector("button");
let lis = document.querySelectorAll("li");
ul.onclick = function(e){
if(e.target.nodeName == "LI"){
console.log(e.target.innerText);
}
}
btn.onclick = function () {
let li = document.createElement("li");
li.innerText = "新来的";
ul.appendChild(li);
};
移动端事件
touch事件基础
事件类型
- touchstart:触摸开始
- touchend:触摸结束
- touchmove:触摸移动
注意事项:
- touch事件在pc端不会被触发,但鼠标事件在pc和移动端都能被触发
- 即使触摸点移出目标元素,touchmove 事件仍然会持续触发,而mousemove事件不会触发
事件对象常用属性
- touches:屏幕上所有的触摸点
- targetTouches:在目标范围内的所有触摸点
- changeTouches:事件触发时,状态发生改变的所有触摸点
-
用一个手指接触屏幕触发事件,此时三个属性有相同的值
-
用第二个手指接触屏幕时,此时,touches有两个元素,每个手指触摸点为一个值。当两个手指触摸相同元素的时候,targetTouches和touches的值相同,而changeTouches此时只有一个值,为第二个手指的触摸点,因为第二个手指是引发事件的原因。
-
用两个手指同时接触屏幕,此时changeTouches有两个值,每个手指的触摸点都有一个值
-
手指滑动,三个值都会发生变化
-
一个手指离开屏幕,touches和targetTouches中对应的元素会同时移出,而changeTouches仍然会存在这个元素
-
手指都离开屏幕后,touches和targetTouches中将不会再有值,changTouches还会有一个值,此值为最后一个离开屏幕的手指的接触点。
触摸点常用属性
- identifier:唯一标识符,单指用不上,多指的时候可以通过该属性来区分开来;
- target:指触发事件的目标元素
- screenX/Y:相对于屏幕的左上角;
- clientX/Y:相对于可视区域左上角;
- pageX/Y:相对于页面左上角