day-039-thirty-nine-20230331-event事件对象
event事件对象
事件句柄
-
鼠标事件
-
click左键单击事件
const box = document.getElementById("box"); box.onclick = function () { console.log("click左键单击事件"); }; -
dblclick左键双击事件
const box = document.getElementById("box"); box.ondblclick = function () { console.log("dblclick左键双击事件"); }; -
mouseover有冒泡移入事件 mouseout有冒泡移出事件
const box = document.getElementById("box"); box.onmouseover = function () { console.log("mouseover有冒泡移入事件"); }; box.onmouseout = function () { console.log("mouseout有冒泡移出事件"); }; -
mouseenter没冒泡移入事件 mouseleave没冒泡移出事件
const box = document.getElementById("box"); box.onmouseenter = function () { console.log("mouseenter没冒泡移入事件"); }; box.onmouseleave = function () { console.log("mouseleave没冒泡移出事件"); }; -
mousemove移动事件,反复触发
const box = document.getElementById("box"); box.onmousemove = function () { console.log("mousemove移动事件"); }; -
mousedown移入按下事件 mouseup移入抬起事件
const box = document.getElementById("box"); box.onmousedown = function () { console.log("mousedown移入按下事件"); }; box.onmouseup = function () { console.log("mouseup移入抬起事件"); }; -
contextmenu右键单击事件,默认出现菜单栏
const box = document.getElementById("box"); box.oncontextmenu = function () { console.log("contextmenu右键单击"); };
-
-
键盘事件
-
事件类型
-
keydown键盘按下事件
const inputText = document.getElementById('inputText') inputText.onkeydown = function(){ console.log('keydown键盘按下事件',inputText.value) } -
keyup键盘抬起事件
const inputText = document.getElementById('inputText') inputText.onkeyup = function(){ console.log('keyup键盘抬起事件',inputText.value) } -
keypress键盘按下抬起事件
-
特殊的键如Control键/Ctrl键、Alt键、Shift键、Esc键,不是适用于该事件
- 监听一个用户是否按下按键请使用 onkeydown 事件,所有浏览器都支持 onkeydown 事件
const inputText = document.getElementById('inputText') inputText.onkeypress = function(){ console.log('keypress键盘按下抬起事件',inputText.value) } -
-
-
事件触发主体
- input元素 textarea元素
- window全局窗口
- document.documentElement
- document.body
-
-
表单事件
-
input值修改事件,内容发生改变就会触发
const inputText = document.getElementById('inputText') inputText.oninput = function(){ console.log('input值修改事件',inputText.value) } -
change值改变事件,内容发生改变并且失去焦点
const inputText = document.getElementById('inputText') inputText.onchange = function(){ console.log('change值改变事件',inputText.value) } -
focus获取焦点事件,blur失去焦点事件
const inputText = document.getElementById('inputText') inputText.onfocus = function(){ console.log('focus获取焦点事件',inputText.value) } inputText.onblur = function(){ console.log('blur失去焦点事件',inputText.value) }
-
-
系统事件
-
scroll监听滚动事件
window.onscroll = function () { console.log("scroll监听滚动事件"); }; -
resize监听视口改变事件,监控页面大小改变就会触发
window.onresize = function () { let theHTML = document.documentElement || document.body; console.log("resize监听视口改变事件", theHTML.clientHeight); }; -
load监听页面渲染事件,页面上所有页面相关的内容加载完毕后最后执行js,如图片及压缩文件等内容都加载出来后
window.onload = function () { console.log("load监听页面渲染事件"); }; -
DOMContentLoaded监听DOM渲染事件,页面上所有页面内容加载完毕后最后执行js,相关的内容如图片及压缩文件等内容不用加载出来
- 支持DOM2的使用,不支持DOM0级的使用
// DOM0---不支持DOMContentLoaded监听DOM渲染事件 document.onDOMContentLoaded = function () { console.log("DOMContentLoaded监听DOM渲染事件-不支持DOM0级事件"); }; // DOM2---支持DOMContentLoaded监听DOM渲染事件 document.addEventListener("DOMContentLoaded", function () { console.log("DOMContentLoaded监听DOM渲染事件-支持DOM2级事件"); });
-
-
移动端事件
-
事件类型
-
touchstart手指按下事件
- click在移动端有300ms的延迟,所以用touchstart事件
let box = document.getElementById("box"); box.ontouchstart = function () { console.log("touchstart手指按下事件"); }; -
touchmove手指移动事件,手指得保持按下的状态并移动才会触发
let box = document.getElementById("box"); box.ontouchmove = function () { console.log("touchmove手指移动事件"); }; -
touchend手指抬起事件
let box = document.getElementById("box"); box.ontouchend = function () { console.log("touchend手指抬起事件"); };
-
-
移动端事件流速事项
- 只能在移动端触发,在PC端不会触发相关的事件
-
每个事件都会自带一个event事件对象
事件默认行为
-
取消事件的默认行为----e.preventDefault()
-
事件绑定函数的那个函数,会自带形参,第一个形参一般为e,是event事件对象的简写
-
浏览器兼容性
-
e.preventDefault() ,FF浏览器,除了IE浏览器之外的其它浏览器
- FF表示除了IE浏览器之外的其它浏览器
-
e.returnValue=false ,IE浏览器去除默认器默认行为
-
-
常见默认行为
-
右键单击----事件默认行为—出现菜单栏
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>取消事件的默认行为</title> </head> <body> <div id="box">aaaa</div> </body> </html> <script> let box = document.getElementById("box"); box.oncontextmenu = function (e) { //会自带形参--e: event事件对象 console.log("oncontextmenu", e); e.preventDefault(); //取消事件默认行为 }; </script> -
a标签----事件默认行为----跳转页面
-
-
事件定义
事件定义,就是指事件绑定的方式
-
DOM0级事件
-
表现方式
-
html与JavaScript代码相混合,不推荐使用
-
实际上就是 行内标签属性的方式
<div onclick="console.log('hahaha')">元素div</div><div onclick="show(10,20)">111</div> <script> function show(n,m){ console.log("111",n,m); } </script>
-
-
html与JavaScript代码相分离,推荐使用
-
实际上就是 DOM元素中js的方式
<div id="box">111</div> <script> box.onclick=function(e){ console.log("111",e); } </script> -
移除事件
<div id="box">111</div> <script> box.onclick=null </script>
-
-
-
原理: 是给元素对象的私有属性赋值
-
每一个事件就是DOM元素对象上的一个属性,就是给DOM元素对象上的属性赋值
-
特色
-
如果同一个事件句柄,绑定多次,后面会把前面的给覆盖
-
如果元素没有某个事件的私有属性,就不能基于这个方法绑定0级事件
// DOM0---不支持DOMContentLoaded监听DOM渲染事件 document.onDOMContentLoaded = function () { console.log("DOMContentLoaded监听DOM渲染事件-不支持DOM0级事件"); }; // DOM2---支持DOMContentLoaded监听DOM渲染事件 document.addEventListener("DOMContentLoaded", function () { console.log("DOMContentLoaded监听DOM渲染事件-支持DOM2级事件"); }); -
事件默认触发阶段必定是冒泡阶段
-
-
-
DOM2级事件—推荐
-
语法:
-
添加事件对应方法: ele.addEventListener(事件句柄,回调函数,事件执行方向) ,FF浏览器-除IE外浏览器
-
事件执行方向
- 事件执行方向: false 冒泡阶段,默认
- 事件执行方向: true 捕获阶段
-
IE浏览器兼容-添加方法: ele.attachEvent(on+事件句柄,回调函数);
- 不能设置事件执行方向,只能冒泡阶段
- IE浏览器在2023年基本上已经被淘汰了,不必兼容
-
-
移除事件方法: ele.removeEventListener(事件句柄,回调函数,事件执行方向) ,FF浏览器-除IE外浏览器
-
事件执行方向
- 事件执行方向: false 冒泡阶段,默认
- 事件执行方向: true 捕获阶段
-
移除事件方法时,回调函数必须是同一个堆/引用地址
-
IE浏览器兼容-移除方法: ele.detachEvent(on+事件句柄,回调函数);
- IE浏览器在2023年基本上已经被淘汰了,不必兼容
-
<div id="box">111</div> <script> box.addEventListener("click",function(e){ console.log("111") }) box.addEventListener("click",function(e){ console.log("222") }) const show = function show(){ console.log("333") } box.addEventListener("click",show) box.removeEventListener("click",show) </script> -
-
原理: 采用的是发布订阅模式----基于事件池实现的-添加方法/放方法,执行方法,移除方法
- 如果同一个事件句柄,绑定多次,全部都会执行
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3VNIUO0C-1680273292510)(./事件池大体思路.png)]
- 如果同一个事件句柄,绑定多次,全部都会执行
-
总结
基于浏览器事件池机制来完成的,通过addEventListener往事件池中增加方法,removeEventListener从中移除方法
-
只要浏览器中有这个事件,都可以通过2级事件来绑定,DOMContentLoaded(jquery中的ready事件就是监听这个事件实现的)
-
同一个事件可以绑定多个方法,触发顺序,先绑定的先触发
-
可以人为规定在捕获或冒泡阶段触发,默认是在冒泡阶段
-
DOM2级事件如果不兼容IE的话需要省去on
- 2023年基本上都要省去on,因为IE浏览器目前已经基本上淘汰过时了
事件周期
-
捕获阶段: 沿着DOM树向下传播,由外向内
- IE浏览器没有捕获阶段
-
目标触发: 监听事件触发
-
冒泡阶段: 沿着DOM向上传播,由内向外
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>取消事件的默认行为</title>
<style>
#divBox {
height: 500px;
width: 500px;
background-color: red;
}
#pBox {
height: 300px;
width: 300px;
background-color: pink;
}
#spanBox {
display: block;
height: 100px;
width: 100px;
background-color: greenyellow;
}
</style>
</head>
<body>
<div id="divBox">
<p id="pBox">
<span id="spanBox">点击这里触发click点击事件</span>
</p>
</div>
</body>
</html>
<script>
let divBox = document.getElementById("divBox");
let pBox = document.getElementById("pBox");
let spanBox = document.getElementById("spanBox");
divBox.onclick = function () {
console.log("DOM0级冒泡-divBox");
};
pBox.onclick = function () {
console.log("DOM0级冒泡-pBox");
};
spanBox.onclick = function () {
console.log("DOM0级冒泡-spanBox");
};
divBox.addEventListener('click', function () {
console.log("DOM2级-不写默认-冒泡-divBox");
});
pBox.addEventListener('click', function () {
console.log("DOM2级-不写默认-冒泡-pBox");
});
spanBox.addEventListener('click', function () {
console.log("DOM2级-不写默认-冒泡-spanBox");
});
divBox.addEventListener('click', function () {
console.log("DOM2级-写true捕获-divBox");
},true);
pBox.addEventListener('click', function () {
console.log("DOM2级-写true捕获-pBox");
},true);
spanBox.addEventListener('click', function () {
console.log("DOM2级-写true捕获-spanBox");
},true);
//DOM2级-写true捕获-divBox
//DOM2级-写true捕获-pBox
//DOM2级-写true捕获-spanBox
//DOM0级冒泡-spanBox
//DOM2级-不写默认-冒泡-spanBox
//DOM0级冒泡-pBox
//DOM2级-不写默认-冒泡-pBox
//DOM0级冒泡-divBox
//DOM2级-不写默认-冒泡-divBox
</script>
阻止事件冒泡
-
e.stopPropagation() , FF浏览器-除IE浏览器外的其它浏览器
- IE浏览器兼容: e.cancelBubble=true
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>取消事件的默认行为</title>
<style>
#divBox {
height: 500px;
width: 500px;
background-color: red;
}
#pBox {
height: 300px;
width: 300px;
background-color: pink;
}
#spanBox {
display: block;
height: 100px;
width: 100px;
background-color: greenyellow;
}
</style>
</head>
<body>
<div id="divBox">
<p id="pBox">
<span id="spanBox">点击这里触发click点击事件</span>
</p>
</div>
</body>
</html>
<script>
let divBox = document.getElementById("divBox");
let pBox = document.getElementById("pBox");
let spanBox = document.getElementById("spanBox");
divBox.onclick = function () {
console.log("DOM0级冒泡-divBox");
};
pBox.onclick = function () {
console.log("DOM0级冒泡-pBox");
};
spanBox.onclick = function () {
console.log("DOM0级冒泡-spanBox");
};
//方向:冒泡方向 由里向外
divBox.addEventListener('click', function () {
console.log("DOM2级-不写默认-冒泡-divBox");
});
pBox.addEventListener('click', function () {
console.log("DOM2级-不写默认-冒泡-pBox");
});
spanBox.addEventListener('click', function () {
console.log("DOM2级-不写默认-冒泡-spanBox");
});
//方向:捕获方向 由外向里
divBox.addEventListener('click', function () {
console.log("DOM2级-写true捕获-divBox");
},true);
pBox.addEventListener('click', function (e) {
e.stopPropagation()//阻止事件冒泡,也阻止事件捕获。//e是形参,表示事件对象。
console.log("DOM2级-写true捕获-pBox");
},true);
spanBox.addEventListener('click', function () {
console.log("DOM2级-写true捕获-spanBox");
},true);
//DOM2级-写true捕获-divBox
//DOM2级-写true捕获-pBox //后续不会再触发事件,因为在这个元素的捕获阶段上调用了e.stopPropagation()。
</script>
目标对象
-
e.target目标对象:事件源,是触发事件的元素(可变的);FF
-
在一个函数被绑定到一个事件后,当该事件被触发时,它始终指向事件被触发的源头。
- 源头就是当前元素或者当前元素的后代元素。
- 事件委托主要就是使用这个属性。
-
IE浏览器兼容: event.srcElement
-
-
this—>绑定事件的元素,如果ES5写法,this就不变
- 在一个函数被绑定到一个事件属性后,一般ES5中this就指向该事件属性所在的元素对象。
- 在一个函数被绑定到一个事件属性后,一般ES6箭头函数中this就指向定义当前函数时当前作用域的this对象。
<body>
<span id="box">box</span>
</body>
<script>
let box = document.getElementById("box");
//目标对象:事件源,是触发事件的元素(可变的)----放大镜
//this---》绑定事件的元素,如果ES5写法,this就不变
box.onclick = function (e) {
console.log("box:-->this:", this); //box
console.log("box:-->e.target:", e.target); //目标对象,自身box
};
document.body.onclick = function (e) {
console.log("body:-->this:", this); //box
console.log("body:-->e.target:", e.target); //目标对象,后代元素box,也可能是自身body。
};
</script>
<body>
<span id="box">box</span>
</body>
<script>
let box = document.getElementById("box");
box.onclick = (e) => {
console.log("box:-->this:", this); //window
console.log("box:-->e.target:", e.target); //目标对象,自身box
};
document.body.onclick = (e) => {
console.log("body:-->this:", this); //window
console.log("body:-->e.target:", e.target); //目标对象,后代元素box,也可能是自身body。
};
</script>
按键编码
在按键相关的事件中,作为形参e传入回调函数的event事件对象中,e.keyCode表示键盘按键的按键编码。
这些编码一般不用记,写这事件后,直接按一下,测一下。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>键码编码</title>
</head>
<body>
<input type="text" id="theInput" />
</body>
</html>
<script>
let theInput = document.getElementById("theInput");
//e.keyCode 键盘按键的按键编码
theInput.onkeydown = function (e) {
console.log("e.keyCode", e.keyCode);
};
</script>
div移动走
<style>
#box {
width: 100px;
height: 100px;
background-color: skyblue;
position: absolute;
}
</style>
<body>
<div id="box"></div>
</body>
<script>
window.onkeydown = function (e) {
let step = 10; //每次移动走 10px
let box = document.getElementById("box");
box.style.position = "absolute";
// let style = window.getComputedStyle(box);
let style = box.getBoundingClientRect();
let theTop = parseInt(style.top) || 0;
let thisTop = theTop;
let theLeft = parseInt(style.left) || 0;
let thisLeft = theLeft;
//console.log(e.keyCode);
//上38 下40 左37 右39
switch (e.keyCode) {
case 38:
thisTop = theTop - step;
console.log(theTop);
box.style.top = `${thisTop}px`;
break;
case 40:
thisTop = theTop + step;
box.style.top = `${thisTop}px`;
break;
case 37:
thisLeft = theLeft - step;
box.style.left = `${thisLeft}px`;
break;
case 39:
thisLeft = theLeft + step;
box.style.left = `${thisLeft}px`;
break;
default:
break;
}
};
</script>
坐标
-
event事件对象的常用坐标属性
-
offsetX/offsetY: 鼠标距离目标元素e.target的左侧/顶部距离 -
clientX/clientY: 鼠标距离视口的左侧/顶部距离x/y: 鼠标距离视口的左侧/顶部距离
-
pageX/pageY: 鼠标距离整个文档document的左侧/顶部距离 -
screenX/screenY: 鼠标距离电脑屏幕的左侧/顶部距离
-
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>坐标</title>
<style>
body {
height: 2000px;
}
#box {
width: 100px;
height: 100px;
background-color: skyblue;
position: fixed;
top: 100px;
left: 200px;
}
</style>
</head>
<body>
<div id="box"></div>
</body>
</html>
<script>
let box = document.getElementById("box");
box.onclick = function handleClick(e) {
console.log(`e.offsetX:`, e.offsetX, ` ;e.offsetY:`, e.offsetY);
console.log(`e.clientX:`, e.clientX, ` ;e.clientY:`, e.clientY);
console.log(`e.x:`, e.x, ` ;e.y:`, e.y);
console.log(`e.pageX:`, e.pageX, ` ;e.pageY:`, e.pageY);
console.log(`e.screenX:`, e.screenX, ` ;e.screenY:`, e.screenY);
};
//e.offsetX: 49 ;e.offsetY: 48
//e.clientX: 249 ;e.clientY: 148
//e.x: 249 ;e.y: 148
//e.pageX: 249 ;e.pageY: 640
//e.screenX: 257 ;e.screenY: 247
</script>