目标:掌握事件绑定处理和事件对象,完成常见网页交互
- 事件监听
- 事件类型
- 事件对象
- 拓展知识
- 综合案例
描述 | 属性/方法 | 效果 |
事件监听 | 元素.addEventListener() | 事件监听,事件绑定,事件注册 |
事件类型 | 鼠标事件 | click 鼠标点击 mouseenter 鼠标进入 mouseleave 鼠标离开 |
焦点事件 | focus 获得焦点 blur 失去焦点 | |
键盘事件 | keydown 键盘按下 keyup 键盘抬起 | |
文本事件 input | 当表单value 被修改时触发 | |
事件对象 | e.key | 判断用户按下哪个键 |
环境对象 | this | 谁调用,指向谁 |
事件监听
监听什么?
以前写的代码都是自动执行的,我们希望一段代码在某个特定的时机才去执行,比如
- 点击按钮可以弹出警示框
- 比如鼠标经过显示下拉菜单等等
像上述功能,需要浏览器时刻监听着用户的行为来做特定的事情(事件),这个就叫做监听
事件
事件是浏览器针对用户的各种行为定义出的一些列的响应机制,当程序在运行时,用户特定的行为就会触发特定的响应机制来执行指定的函数代码
- 比如用户点击按钮时,可以 触发
click
事件,弹出警示框
- 比如用户使用鼠标划入某个盒子时,可以触发
mouseenter
事件,显示下拉菜单
事件监听基本用法
事件监听也称为: 事件注册、事件绑定
语法:
元素对象.addEventListener('事件类型', 事件处理函数)
事件监听三要素
- 事件源(哪个元素对象被触发了) -> 事件监听是将事件处理函数注册到元素对象身上
- 事件类型 (什么情况下触发,点击还是鼠标经过等)
- 事件处理函数(要做什么事情,是弹出警告框,还是修改元素值,还是修改css属性)
<!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><button class="btn">唐伯虎</button><script>// 需求: 点击button按钮,页面会弹出一个警示框,内容显示 '秋香'// 事件监听语法:// 元素对象.addEventListener('事件类型', 事件处理函数)// 1. 获取元素对象 button按钮const btn = document.querySelector('.btn')// 2. 事件监听 btn.addEventListener('click', function () {alert('秋香')})</script></body></html>
注意:
1.事件类型要加引号,小写
2.函数是点击之后再去执行,每次点击都会执行一次
事件监听-随堂练习
需求:点击关闭按钮之后,关掉登录提示盒子
分析:
①:事件源: 关闭按钮 a链接
②:事件类型:鼠标点击 click
③:事件处理程序:关闭的是父盒子
核心:利用样式的显示和隐藏完成, display:none 隐藏元素 display:block 显示元素
图片素材下载:📎images.rar
<!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><style>.pop {display: block;visibility: visible;position: fixed;z-index: 9999;left: 50%;top: 50%;width: 530px;height: 254px;margin-top: -127px;margin-left: -265px;background: url(./images/login.webp) no-repeat;}.close {position: absolute;right: 0;top: 0;width: 40px;height: 40px;}</style>
</head><body><div class="pop"><a href="javascript:;" class="close"></a></div><script>// 点击关闭按钮可以关闭父盒子// 确定事件三要素:// 1. 事件源: a链接// 2. 事件类型:鼠标点击事件click// 3. 事件处理函数: 将div.pop盒子关闭</script>
</body></html>
<!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><style>.pop {display: block;visibility: visible;position: fixed;z-index: 9999;left: 50%;top: 50%;width: 530px;height: 254px;margin-top: -127px;margin-left: -265px;background: url(./images/login.webp) no-repeat;}.close {position: absolute;right: 0;top: 0;width: 40px;height: 40px;}</style>
</head><body><div class="pop"><a href="javascript:;" class="close"></a></div><script>// 点击关闭按钮可以关闭父盒子// 确定事件三要素:// 1. 事件源: a链接// 2. 事件类型:鼠标点击事件click// 3. 事件处理函数: 函数体代码为 将.pop盒子关闭// 获取父盒子const pop = document.querySelector('.pop')// 1. 事件源 a链接const closeBtn = document.querySelector('.close')// 2. 注册事件closeBtn.addEventListener('click', function () {// 3. 关闭父盒子 主要利用 display:nonepop.style.display = 'none'})</script>
</body></html>
回调函数
回调函数:当一个函数当做参数来传递给另外一个函数的时候,这个函数就是回调函数(回头调用的函数)
作用:完成某些特定任务
javascript"><script>// 1. 定时器间隔函数,里面第一个参数又是函数,这个匿名函数就是回调函数setInterval(function () {console.log('我是回调函数')}, 1000)// 2. addEventListener 函数的第二个参数也是函数,这个匿名函数也是回调函数btn.addEventListener('click', function () {console.log('我是回调函数')})
</script>
回调函数本质还是函数,只不过把它当成参数使用
使用匿名函数做为回调函数比较常见
事件监听版本(扩展阅读)
事件监听发展史:
DOM L0 :是 DOM 刚诞生的版本,使用 事件源.on事件类型 来注册事件
DOM L1:DOM级别1 于1998年10月1日成为W3C推荐标准
DOM L2:使用addEventListener注册事件
DOM L3: DOM3级事件模块在DOM2级事件的基础上重新定义了这些事件,也添加了一些新事件类型
我们常用DOM L0 和 DOM L2方式来注册事件:
- DOM0 事件 事件源.on事件类型 = function() { }
javascript">btn.onclick = function () {alert('我是弹窗1')
}
- DOM 2事件事件源.addEventListener(事件类型,事件处理函数)
javascript">btn.addEventListener('click', function () {console.log('我是回调函数')
})
区别:
on 方式同名事件会被覆盖 -> 场景:一个Dom元素身上同名事件只注册一次
addEventListener则不会 -> 场景:一个Dom元素身上同名事件要注册多次
事件类型
将众多的事件类型可分为:
- 鼠标事件
- 键盘事件
- 表单事件
- 焦点事件等
我们逐一展开学习。
事件类型的大小写敏感的字符串,统一用小写字母
鼠标事件
鼠标事件是指跟鼠标操作相关的事件,如单击、经过等。
javascript"><body><div class="box"></div><script>// 鼠标事件类型const box = document.querySelector('.box')// 1. 鼠标点击box.addEventListener('click', function () {console.log('我点击了盒子')})// 2. 鼠标进入box.addEventListener('mouseenter', function () {console.log('我鼠标经过了盒子')})// 3. 鼠标离开box.addEventListener('mouseleave', function () {console.log('我鼠标离开了盒子')})</script></body>
随堂练习
需求:实现轮播图点击切换功能,功能要求如下
- 进入页面时轮播图按照顺序自动轮播 - 使用setInterval技术
- 当鼠标进入轮播图时,停止自动轮播,离开轮播后,恢复自动轮播 -使用mouseenter和mouseleave事件
- 当点击>按钮时,轮播图顺序切换图片,点击<按钮时,轮播图倒序切换图片-使用click事件
<!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><style>* {box-sizing: border-box;}.slider {width: 560px;height: 400px;overflow: hidden;}.slider-wrapper {width: 100%;height: 320px;}.slider-wrapper img {width: 100%;height: 100%;display: block;}.slider-footer {height: 80px;background-color: rgb(100, 67, 68);padding: 12px 12px 0 12px;position: relative;}.slider-footer .toggle {position: absolute;right: 0;top: 12px;display: flex;}.slider-footer .toggle button {margin-right: 12px;width: 28px;height: 28px;appearance: none;border: none;background: rgba(255, 255, 255, 0.1);color: #fff;border-radius: 4px;cursor: pointer;}.slider-footer .toggle button:hover {background: rgba(255, 255, 255, 0.2);}.slider-footer p {margin: 0;color: #fff;font-size: 18px;margin-bottom: 10px;}.slider-indicator {margin: 0;padding: 0;list-style: none;display: flex;align-items: center;}.slider-indicator li {width: 8px;height: 8px;margin: 4px;border-radius: 50%;background: #fff;opacity: 0.4;cursor: pointer;}.slider-indicator li.active {width: 12px;height: 12px;opacity: 1;}</style>
</head><body><div class="slider"><div class="slider-wrapper"><img src="./images/slider01.jpg" alt="" /></div><div class="slider-footer"><p>对人类来说会不会太超前了?</p><ul class="slider-indicator"><li class="active"></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li></ul><div class="toggle"><button class="prev"><</button><button class="next">></button></div></div></div><script>// 初始数据对象数组const sliderData = [{ url: './images/slider01.jpg', title: '对人类来说会不会太超前了?', color: 'rgb(100, 67, 68)' },{ url: './images/slider02.jpg', title: '开启剑与雪的黑暗传说!', color: 'rgb(43, 35, 26)' },{ url: './images/slider03.jpg', title: '真正的jo厨出现了!', color: 'rgb(36, 31, 33)' },{ url: './images/slider04.jpg', title: '李玉刚:让世界通过B站看到东方大国文化', color: 'rgb(139, 98, 66)' },{ url: './images/slider05.jpg', title: '快来分享你的寒假日常吧~', color: 'rgb(67, 90, 92)' },{ url: './images/slider06.jpg', title: '哔哩哔哩小年YEAH', color: 'rgb(166, 131, 143)' },{ url: './images/slider07.jpg', title: '一站式解决你的电脑配置问题!!!', color: 'rgb(53, 29, 25)' },{ url: './images/slider08.jpg', title: '谁不想和小猫咪贴贴呢!', color: 'rgb(99, 72, 114)' },]// 1. 利用随机数选取数组中的一个对象let index = 0function setSwiperData() {let data = sliderData[index]// 将data中的各种属性设置到网页的相关元素即可// 2. 利用选取的对象来更换图片// 需求:把图片元素的地址换成数据里面的图片地址// 2.1 获取图片元素 const imgBox = document.querySelector('.slider-wrapper img')// 2.2 把随机生成的图片地址 赋值给 图片元素.src imgBox.src = data.url// 3. 更换文字内容// 3.1 获取文字盒子 p const pBox = document.querySelector('.slider-footer p')// 3.2 把随机生成的文字赋值给 p元素.innerText 或者 innerHTMLpBox.innerHTML = data.title// 4. 更换背景颜色 slider-footer 盒子// 4.1 获取 slider-footer 盒子 const divBox = document.querySelector('.slider-footer')// 4.2 把随机生成的背景颜色赋值给 footer元素 styledivBox.style.backgroundColor = data.color// 5. 更换小圆点// 5.1 先选择对应的小圆点const liBox = document.querySelector(`.slider-indicator li:nth-child(${index + 1})`)// 5.2 让选出来的小圆点高亮显示// 将已经有小圆点样式的li标签上的class的active移除const activeBox = document.querySelector('.active')activeBox.classList.remove('active')liBox.classList.add('active')}let timerId = setInterval(function () {// 将index加1index++if (index >= sliderData.length) {// 将index重置回0index = 0}setSwiperData()}, 1000)/*基于昨天的综合案例,扩展如下需求1. 鼠标进入盒子,停止自动轮播-> 技术拆解1. 事件源:div.slider2. 事件类型: mouseenter3. 事件函数代码逻辑:clearInterval(定时器的id)2. 离开盒子,重新开启自动轮播->技术拆解1. 事件源:div.slider2. 事件类型: mouseleave3. 事件函数代码逻辑:setInterval重新开启2. 用户点击< 和 > 自动切换图片技术拆解:1. 事件源: < .prev > .next2. 事件类型:点击事件 click3. 事件函数*//*需求1:1. 鼠标进入盒子,停止自动轮播-> 技术拆解1. 事件源:div.slider2. 事件类型: mouseenter3. 事件函数代码逻辑:clearInterval(定时器的id)*/const silderBox = document.querySelector('.slider')silderBox.addEventListener('mouseenter', function () {// clearInterval(定时器的id)clearInterval(timerId)})/*需求2:2. 离开盒子,重新开启自动轮播->技术拆解1. 事件源:div.slider2. 事件类型: mouseleave3. 事件函数代码逻辑:setInterval重新开启*/silderBox.addEventListener('mouseleave', function () {timerId = setInterval(function () {// 将index加1index++if (index >= sliderData.length) {// 将index重置回0index = 0}setSwiperData()}, 1000)})/*需求3:2. 用户点击< 和 > 自动切换图片技术拆解:1. 事件源: < .prev > .next2. 事件类型:点击事件 click3. 事件函数*/const nextBox = document.querySelector('.next')nextBox.addEventListener('click', function () {// 将index加1index++if (index >= sliderData.length) {// 将index重置回0index = 0}setSwiperData()})const prevBox = document.querySelector('.prev')prevBox.addEventListener('click',function(){// index减1index--if(index <0){// 如果为负数,则让图片从数组的最后一个数据开始轮播index = sliderData.length - 1}setSwiperData()})</script>
</body></html>
焦点事件
主要是针对于表单是否获得光标的事件, 获得焦点 focus 、失去焦点 blur
<!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><style>[type=text] {width: 245px;height: 50px;padding-left: 20px;border: 1px solid #ccc;font-size: 17px;outline: none;}</style></head><body><input type="text" class="search-text"><input type="text" class="search"><script>// 1. 焦点事件(手动触发)const search_text = document.querySelector('.search-text')// 1.1 获得焦点 focussearch_text.addEventListener('focus', function () {console.log('获得了焦点')})// 1.2 失去焦点 blursearch_text.addEventListener('blur', function () {console.log('失去了焦点')})// 2. 拓展 自动获得焦点 focus() 自动失去焦点 blur()// 2.1 语法: 元素.focus() 比如百度首页搜索框自动获得焦点const search = document.querySelector('.search')search.focus()</script></body></html>
键盘事件和 input事件
事件 | 触发时机 | 得到表单值 |
keydown | 按下键盘时触发 | 内容获取-不完整 |
keyup | 弹起键盘时触发 | 输入内容-完整 |
input | 表单value发生变化时触发 | 输入内容 -完整 |
<!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>input事件和键盘事件</title><style>textarea {width: 300px;height: 30px;padding: 10px;border-color: transparent;outline: none;resize: none;background: #f5f5f5;border-radius: 4px;}</style></head><body><textarea id="tx" placeholder="发一条友善的评论" rows="2"></textarea><script>// 获取元素const tx = document.querySelector('#tx')// 1. 键盘事件 // 1.1 键盘按下事件 keydown 当我们按下键盘的时候就触发tx.addEventListener('keydown', function () {console.log('我是keydown事件' + tx.value)})// 1.2 键盘弹起事件 keyup 当我们键盘弹起的时候就触发tx.addEventListener('keyup', function () {console.log('我是keyup事件' + tx.value)})// 2. 用户输入事件 input ,是表单value的值发生变化的时候触发tx.addEventListener('input', function () {console.log('我是input事件' + tx.value)})// 3. 注意事项// 3.1 执行顺序 keydown → input → keyup// 3.2 keydown 获取值的时候得不到最后一次按键的值, keyup和input可以得到用户输入内容</script></body></html>
注意事项
- 执行顺序 keydown → input → keyup
- keydown 获取值的时候得不到最后一次按键的值, keyup和input可以得到用户输入内容
事件对象
事件对象是什么?
注册事件中,回调函数的第一个参数就是事件对象,一般命名为event、ev、e
- 事件对象里保存了:事件触发时的相关信息,包含属性和方法
- 例如:鼠标点击事件中,事件对象就存了事件源的信息
使用场景
- 可以判断用户按下哪个键,比如按下回车键可以发布新闻
- 可以判断鼠标点击了哪个元素,从而做相应的操作
<body><div class="box"></div><textarea id="tx" placeholder="发一条友善的评论" rows="2"></textarea><script>// 事件对象const box = document.querySelector('.box')box.addEventListener('click', function (e) {console.log(e)console.log(e.target) // target保存了事件源信息})const tx = document.querySelector('#tx')tx.addEventListener('keyup', function (e) {// e 就是事件对象// console.log(e)// console.log(e.key) // a // 用户如果按下的是回车键,则弹出框提示按下了回车键if (e.key === 'Enter') {alert('您按下了回车键')}})</script></body>
事件对象常见属性
事件回调函数的【第1个参数】即所谓的事件对象,通常习惯性的将这个对数命名为 event
、ev
、ev
。
随堂练习
需求:按下回车键,可以发布评论
功能:
①:按下回车,可以显示评论信息,并且评论内容显示到对应位置
②:输入完毕,文本域清空内容
<!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><style>.wrapper {width: 800px;display: flex;justify-content: flex-end;}.wrapper textarea {height: 50px;flex: 1;padding: 10px;border-radius: 4px;border-color: #e4e4e4;background: #fff;outline: none;resize: none;}.wrapper button {width: 70px;margin-left: 10px;border: none;color: #fff;background: #00aeec;border-radius: 4px;cursor: pointer;}.wrapper .total {margin-right: 80px;margin-top: 5px;color: #999;}.list {width: 800px;border: 1px solid #efce9c;background-color: rgb(231, 238, 191);padding: 10px;}.list p {font-size: 12px;}</style>
</head><body><div class="wrapper"><textarea id="tx" placeholder="发一条友善的评论" rows="2" maxlength="200"></textarea><button>发布</button></div><div class="wrapper"><span class="total">0/200字</span></div><div class="list"><p>评论信息:</p><p class="msg">善语结善缘~~请发表你的评论</p></div><script>/*需求:1. 获取用户在文本域元素中的内容,并且回车表示发表动作-> 找事件源 id="tx" -> 事件类型:keyup 2. 获取到文本内容之后,将这个内容更新到p元素->事件函数要完成的事情*/const textBox = document.querySelector('#tx')textBox.addEventListener('keyup', function (e) {// 判断如果用户按的是回车键,表示发表评论if (e.key === 'Enter') {// 2. 获取到文本内容之后,将这个内容更新到p元素document.querySelector('.msg').innerHTML = textBox.value // 清空文本域中的内容textBox.value = ''}})</script>
</body></html>
环境对象-this
环境对象:指的是函数内部特殊的 this , 它指向一个对象,调用方式不一样,this指向的对象也不一样
作用:弄清楚this的指向,可以让我们更方便编写代码
javascript">function fn() {console.log(this) // this 指向哪个对象?
}
// fn() // 直接调用函数fn(),其实相当于是 window.fn()
window.fn()const obj = {uname: '佩奇',sayHi: function () {console.log(this) // this指向哪个对象?}
}
obj.sayHi()const btn1 = document.querySelector('button')
btn1.addEventListener('click', function () {console.log(this) // this指向哪个对象?
})
<body><button>点击</button><script>// 环境对象 this 粗略规则: 谁调用函数,this就指向谁// 1. 全局环境// console.log(this) // this 指向 window 全局对象// 2. 普通函数function fn() {console.log(this) // this 指向 window 全局对象}window.fn()// 3. 对象方法const obj = {uname: '佩奇',sayHi: function () {console.log(this) // this 指向 obj对象}}obj.sayHi()// 4. 事件const btn1 = document.querySelector('button')btn1.addEventListener('click', function () {console.log(this) // this 指向 btn 这个对象 })</script></body>
特点:
- 函数的调用方式不同,this 指代的对象也不同
- 【谁调用, this 就是谁】 是判断 this 指向的粗略规则
- 直接调用函数,其实相当于是 window.函数,所以 this 指代 window
排他思想
是一种思路,目的是突出显示某个元素
比如,有多个元素,当鼠标点击某个元素时,只有被点击的元素会添加高亮样式,其余的元素移除样式
口诀:注意顺序
①:排除其他人
②:保留我自己
基本用法
<!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><style>.pink {background-color: pink;}</style>
</head><body><button class="pink">按钮1</button><button class="pink">按钮2</button><button>按钮3</button><button>按钮4</button><button>按钮5</button><script>// 1. 向5个按钮注册点击事件const bts = document.querySelectorAll('button')for(let i = 0;i<bts.length;i++){bts[i].addEventListener('click',function(e){// console.log(e.target)// 将其他元素身上的pink类移除掉const pinks = document.querySelectorAll('.pink')for(let j=0;j<pinks.length;j++){pinks[j].classList.remove('pink')}// 谁点击了就加上pink这个类到自己身上e.target.classList.add('pink')})}</script>
</body></html>