目录
(2)使用addEventListener来注册事件⭐️⭐️⭐️
1.定义
事件是指用户的某种行为或浏览器自身执行的某种动作,响应这些动作的代码称为事件处理程序。
JavaScript 通过事件驱动模型允许你为特定事件设置处理函数,当这些事件发生时,相应的处理函数就会被触发执行。
2.事件组成
事件由三部分组成
- 事件源:给某元素绑定事件,该元素被称为事件源;
- 事件类型:如点击事件click;
- 事件处理程序:handler
3.注册/移除事件
[1]注册事件
注册事件有两种方式,一种是使用on关键字来进行事件注册,另一种是通过addEventListener方法进行事件注册。
(1)on关键字
[1]行内式
<element onxxx='执行代码'><element>
<!-- 该div元素点击时会在控制台打印111-->
<div onclick='console.log(111)'>点击打印<div>
<!-- 行内式绑定的是执行代码, 若是绑定方法需要设置为方法的调用!!! -->
<div onclick='toCon()'>点击打印<div>
<script>
function toCon(){
console.log(111)
}
</script>
[2]通过属性绑定的方式注册事件
element.onxxx = function(){...}
const box = document.querySelector('div')
box.onclick = function(){
console.log(111)
}
使用on关键字注册事件的特点是 如果同一个元素拥有多个相同事件,那么后面的事件会覆盖前面的事件--->也就是说若是使用on关键字注册事件,同一元素不能注册相同的事件!
box.onclick = function () {
console.log('大家好,我是班长');
}
box.onclick = function () {
console.log('大家好,我是课代表');
}
上述代码中当box元素被点击时会在控制台打印'大家好,我是课代表'
(2)使用addEventListener来注册事件⭐️⭐️⭐️
使用addEventListener注册事件,可以实现给一个元素,设置多个相同的事件
(1)语法
element.addEventListener(事件类型,事件方法,true/false)
第三个参数为false那么该事件为冒泡事件,若是为true那么该事件为捕获事件
- eg注册点击事件
-
function fun1() { console.log('大家好,我是班长'); } addEventListener('click' fun1,false)
[2]移除事件
(1)on关键字注册的事件在移除时直接置空;
// 1. 利用on设置事件
box.onclick = function () {
console.log('我只能打印一次');
// 点击完之后立刻清空点击事件
this.onclick = null;
}
(2)addEventListener注册事件使用removeEventListener方法移除事件
function fun() {
console.log('我只能打印一次');
// 点击完之后移除事件
// removeEventListener()
// add怎么赋值,remove就怎么赋值
box.removeEventListener('click',fun,false)
}
- 需要注意:在使用removeEventListener进行事件移除时,需要传入完全相同的参数
-
function myEventHandler(event) { // ... 处理逻辑 } // 添加 element.addEventListener('click', myEventHandler); // 移除 (正确:传入相同的函数引用) element.removeEventListener('click', myEventHandler); // 移除 (错误:传入的是匿名函数,无法移除) element.addEventListener('click', () => { console.log('匿名函数'); }); element.removeEventListener('click', () => { console.log('匿名函数'); }); // 这行无效!
-
4.事件对象
当事件发生时➡️事件处理函数被调用,浏览器会创建一个事件对象,并将其作为参数传递给事件处理函数。这个对象包含了有关事件的详细信息,例如事件类型、目标元素等。
注意:若是行内式给元素绑定事件时,若是绑定的是方法的调用,需要手动将事件对象event传入,否则获取不到事件对象。
<a href="https://www.baidu.com/" onclick="bandA()">跳转到百度</a>
<script>
function bandA(e){
console.log(e) // undefined
}
</script>
<!--传递的值必须是event,否则获取不到!-->
<a href="https://www.baidu.com/" onclick="bandA(e)">跳转到百度</a>
<script>
function bandA(e){
console.log(e) // undefined
}
</script>
<a href="https://www.baidu.com/" onclick="bandA(event)">跳转到百度</a>
<script>
function bandA(e){
console.log(e) // 事件对象
}
</script>
[1]获取触发事件的元素
e.target
在这里需要注意e.target与this的区别
- this: 事件源也就是绑定事件的元素
- e.target: 此时被点击的元素
[2]获取该事件的事件类型
e.type
[3]阻止事件的默认行为
e.preventDefault();
[4]阻止事件的冒泡/捕获
e.stopPropagation()
示例
<!-- 当点击下述a标签时会跳转到百度首页 -->
<a href="https://www.baidu.com/">跳转到百度</a>
<!-- 若是不想跳转,可以阻止a标签的默认行为来阻止a标签跳转 -->
<a href="https://www.baidu.com/" onclick="bandA(event)">跳转到百度</a>
<script>
function bandA(e){
e.preventDefault()
}
</script>
5.事件流
当事件发生在具有父元素的元素上,浏览器会经历两个阶段
- 捕获阶段:事件从
window
对象向下传播到目标元素的父级过程 - 目标阶段:事件到达目标元素本身
- 冒泡阶段:事件从目标元素开始向上冒泡回
window
对象
[1]什么事件为冒泡事件;什么事件是捕获事件
- 使用on注册的事件是冒泡事件;
- 使用addEventListener注册的事件
- 若是第三个参数为false则是冒泡事件;
- 若是第三个参数为true若是捕获事件;
- tips:不传第三个参数默认是冒泡事件;
举例说明
- 使用onxxx注册事件,默认是冒泡事件
<style> .out{ width: 200px; height: 200px; border: 1px solid red; } .inner{ width: 100px; height: 100px; border: 1px solid red; } </style>
<div class="out"> <div class="inner"></div> </div> <script> // 5.事件流 const out = document.querySelector('.out') const inner = document.querySelector('.inner') out.onclick = function(){ console.log('out') } inner.onclick = function(){ console.log('inner') } </script>
当点击inner元素时【1】执行目标元素➡️打印inner【2】冒泡➡️打印out
-
使用addEventListener注册捕获事件
-
<style> .out{ width: 200px; height: 200px; border: 1px solid red; } .inner{ width: 100px; height: 100px; border: 1px solid red; } </style>
当点击inner元素时【1】捕获➡️打印out 【2】执行目标元素➡️打印inner<script> // 5.事件流 const out = document.querySelector('.out') const inner = document.querySelector('.inner') inner.addEventListener('click', function(){ console.log('inner') },true) out.addEventListener('click', function(){ console.log('out') },true) </script>
[2]阻止事件冒泡/事件捕获
- 即可以阻止事件冒泡又可以阻止事件捕获
- e.stopPropagation();
- 阻止事件冒泡
- e.cancelBubble();
6.如何理解事件委托
[1]定义:事件委托简单来说就是:事件不直接绑定在某个元素上而是绑定在该元素的父元素上,进行触发的时候再通过条件进行判断;
[2]优点:
- 大量节省内存占用,减少注册事件;
- 当在新增加子对象时,无需再对齐进性事件绑定,对于动态内容比较友好;
[3]举例说明
如下,若是我们为li设置点击事件,需要循环设置10个点击事件(但是若是li元素有成千上百个呢,直接为li元素设置点击事件就不太友好了),事件代理仅需设置一个点击事件就可以完成所需功能!
<ul id="ul">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ul>
<script>
let ul = document.getElementById('ul')
ul.onclick=function(e){
console.log(e.target.innerHTML);
}
</script>
7.事件类型
注:事件不采用驼峰命名,都是用小写
1)鼠标事件
点击事件 | click |
双击事件 | dblclick |
鼠标按下事件 | mousedown |
鼠标释放事件 | mouseup |
鼠标移入事件-鼠标指针移入元素本身(不冒泡) | mouseenter |
鼠标移出事件-鼠标指针移出元素本身(不冒泡) | mouseleave |
鼠标移入事件-鼠标指针移入元素本身/子元素(冒泡) | mouseover |
鼠标移出事件-鼠标指针移出元素本身/子元素(冒泡) | mouseout |
鼠标在元素/子元素内持续移动时触发 | mousemove |
鼠标尝试打开上下文菜单时触发 | contextmenu |
鼠标事件中事件对象的属性
- clientX/clientY: 相对于浏览器窗口左上角的鼠标指针的X和Y的坐标
- pageX/pageY: 相对于页面左上角的鼠标指针的X和Y的坐标
示例1: 鼠标移入文本放大展示
<style>
div{
width: 200px;
height: 100px;
border:1px solid #666;
}
.display-font{
font-size: 20px;
}
</style>
<div onmouseenter="changeSize(event,1)" onmouseleave="changeSize(event, 2)" >详细说明</div>
<script>
function changeSize(e, type){
const box = document.querySelector('div')
switch(type){
case 1:
box.setAttribute('class', 'display-font')
break
case 2:
box.removeAttribute('class')
}
}
</script>
示例2: 禁止打开右侧菜单
<div>
<p>我是一个兵,来自老百姓。我是一个兵,来自老百姓。我是一个兵,来自老百姓。我是一个兵,来自老百姓。我是一个兵,来自老百姓。我是一个兵,来自老百姓。我是一个兵,来自老百姓。我是一个兵,来自老百姓。我是一个兵,来自老百姓。我是一个兵,来自老百姓。</p>
</div>
<script>
const pBox = document.querySelector('p')
pBox.oncontextmenu = function(e){
// 取消事件的默认行为
e.preventDefault()
}
</script>
2)键盘事件
- [1]键盘按下时触发:onkeydown
- 当用户按下任意键时立即触发
- 如果按住某个键不放,
keydown
会持续触发(取决于键盘的重复速率设置)
- [2]键盘弹起时触发: onkeyup
- 当用户释放按键时触发
- 每次按键只触发一次,即使用户长时间按住某个键也不会重复触发
键盘事件中事件对象的属性
[1]key:返回被按下的键的实际值
document.addEventListener('keydown', function(e){
console.log(e.key) // 按下a键则打印a,按下左箭头则打印ArrowLeft
}, false)
[2]code:表示物理按键的位置,不受键盘布局影响。
[3]keycode:返回触发事件的键的 ASCII 值(已被废弃,还支持)
[4]ctrlKey/shiftKey/altKey/metaKey: 布尔值,判断是否同时按下 Ctrl
, Shift
, Alt
, 或 (
Windows 键或 Mac 上的 Command 键)
[5]repeat:对于 keydown
事件,如果一个键被持续按下,则该属性为 true
,可用于区分长按和短按
示例1: 京东搜索框案例
打开京东首页,当点击“s”键时搜索框会自动聚焦。
<input type="text" placeholder="请输入">
<script>
document.addEventListener('keyup', function(e){
console.log('e.key',e.key)
if(e.key === 's') {
// 聚焦搜索框
const searchBox = document.querySelector('input')
searchBox.focus()
}
}, false)
在此需要监听keyup事件,若是监听keydown事件 => 在键盘按下的时候就会聚焦,那么s相当于输入到input框中了。
示例2: 通过上下左右箭头控制元素移动
在很多游戏中,会通过上下左右箭头控制人物进行移动,其实就是通过监听键盘按下事件实现的。
<style>
.screen{
width: 300px;
height: 600px;
border: 1px solid #666;
padding: 50px;
position: relative;
}
.person{
width: 30px;
height: 30px;
background-color: red;
position: absolute;
top:50%;
left:50%;
transform: translate(-50%, -50%);
}
</style>
<div class="screen">
<div class="person"></div>
</div>
<script>
const person = document.querySelector('.person')
let topL = parseInt(window.getComputedStyle(person).top)
let leftL = parseInt(window.getComputedStyle(person).left)
document.onkeydown = function(e){
switch(e.key){
case 'ArrowUp':
if(topL >= 25){
topL = topL - 10
} else if(topL<25 && topL>15) {
topL = 15
}
break
case 'ArrowDown':
// 边界值top+15 = 700
if(topL <= 675){
topL += 10
} else if(topL>675 && topL<685) {
topL = 685
}
break
case 'ArrowLeft':
// left-15 = 0
if(leftL >= 25){
leftL = leftL - 10
} else if(leftL<25 && leftL>15) {
leftL = 15
}
break
case 'ArrowRight':
if(leftL <= 375){
leftL += 10
} else if(leftL>375 && leftL<385) {
leftL = 385
}
break
}
person.style.left = leftL + 'px'
person.style.top = topL + 'px'
}
</script>
3)表单元素的事件
input | input/textarea元素的值发生变化时触发➡️实时响应用户输入的首选 |
select | 用户在input/textarea元素中选中文本时触发 |
change | input/textarea/select元素的值发生改变时触发 |
focus | 表单元素获取焦点时触发 |
blur | 表单元素失去焦点时触发 |
submit | 当表单被提交时触发(如点击提交按钮或按回车)。监听在 form 元素上,常用 event.preventDefault() 来阻止表单默认提交行为以进行验证。 |
reset | 当表单被重置(点击 type="reset" 的按钮)时触发 |
表单元素常用的事件如下:
示例1:当输入框中内容改变的时候,打印输入框中的内容;
<body>
<input type="text" id="input" />
<script>
let inputBox = document.getElementById('input')
inputBox.oninput = function () {
console.log(inputBox.value)
}
</script>
</body>
示例2:当输入框获取焦点时,选中输入框中的所有内容
<input type="text" placeholder="百度一下">
<script>
const searchBox = document.querySelector('input')
searchBox.onfocus = function(){
if (!searchBox.value){
searchBox.value = searchBox.placeholder
}
searchBox.select()
}
</script>
4)窗口/文档/资源事件
load | 当整个页面及所有依赖资源(如样式表、图片)已完成加载时触发 | 在window上触发;也可在img/script等标签使用 |
DOMContentLoaded | 当初始的 HTML 文档被完全加载和解析完成时触发 无需等待样式表、图片加载完毕➡️执行初始化逻辑的最佳时机,比 | 在documents上触发 |
resize | 浏览器窗口大小改变时触发 常用于实现响应式布局调整 | 在window上触发 |
scroll | 用户滚动页面或元素时触发 常用于实现无限滚动、导航栏隐藏等效果 | |
hashchange | 当 URL 的锚部分(即 # 号后面的部分)发生改变时 实现单页面应用 (SPA) 的路由 | 在window上触发 |
unload | 当用户退出页面时触发 现在较少使用,更多地转向 | |
beforeunload | 在即将卸载页面之前触发,允许显示一个确认对话框询问用户是否真的要离开 |
4)移动端的触摸事件
touchstart | 当手指触摸到一个元素上时触发 |
touchend | 当手指从屏幕上抬起时触发 |
touchmove | 当手指在屏幕上滑动时持续触发 |
touchcancel | 当触摸被意外中断(如来电提示)时触发 |
5)盒子拖拽事件(html5新增)
- [1]盒子拖拽事件
- 1)开始拖拽:ondragstart
- 2)拖拽过程中:ondrag
- 3)结束拖拽:ondragend
- [2]容器拖拽事件
- 1)具有拖拽元素进入容器:ondragenter
- 2)具有拖拽元素的盒子在容器中移动:ondragover
- 3)具有拖拽元素的盒子离开容器:ondragleave
- 4)具有拖拽元素的盒子进入容器后松手:ondrop
- 注:执行4事件必须禁止2事件的默认效果;
6)视频音频事件
- [1]视频/音频的开始播放事件:onplay
- [2]音频/视频的暂停播放事件:onpause
7)复制事件
- copy:当用户点击复制时触发
- 注:若是禁止该事件的默认行为,虽然复制还是可以点击,但是内容并不会被复制成功
- selectstart:当用户开始选择(选中)页面上的内容时触发的事件
示例1: 当用户想要复制页面内容时,提示开通会员再复制
<p>我是一个兵 来自老百姓111</p>
<script>
const isMember = 0 // 模拟后端数据非会员
document.addEventListener('selectstart', function(e){
if (!isMember){
alert('请先开通会员再来复制吧~')
e.preventDefault()
}
}, false)
</script>
8.事件阶段
事件分为三大阶段
- 捕获事件
- 当某个事件被触发之后,那么它所有的 父元素 相同的事件 也会被触发;
- 执行顺序:在捕获的过程中,最外层(根)元素的事件先被触发,然后依次向内执行,直到触发最里面的元素(事件源)--->由外到内,由父到子;
- 目标事件(正常事件)
- 冒泡事件
- 当某个元素的事件被触发之后,那么它所有的 父元素 相同的事件 也会被触发;
- 执行顺序:由内到外,从小到大;