一、 事件对象
事件对象也是个对象,这个对象里有事件触发时的相关信息。
例:鼠标点击事件中 事件对象就存了鼠标点在哪个位置等信息
1. 事件对象在哪里
- 在事件绑定的回调函数的第一个参数就是事件对象
2. 使用场景
- 可以判断用户按下哪个键,比如按下回车键可以发布新闻
- 可以判断鼠标点击了哪个元素,从而做出相应的操作
3. 获取事件对象
- 在事件绑定的回调函数第一个参数就是事件对象
- 一般命名为event、ev、e
元素.addEcentListener('click',function(e){})
4. 部分常用属性
- type :获取当前的事件类型
- clientX/clientY : 获取光标相对于浏览器可见窗口左上方的位置
- offsetX/offsetY :获取光标相对于当前DOM元素左上角的位置
- key : 用户按下的键盘键的值(现在不提倡使用keyCode)
二、事件类型
1. 鼠标事件 (鼠标触发)
- click 鼠标点击
- mouseenter 鼠标经过
- mouseleave 鼠标离开
2. 焦点事件 (表单获得光标)
- focus 获得焦点
- blue 失去焦点
3. 键盘事件 (键盘触发)
- keydown 键盘按下触发
- keyup 键盘抬起触发
4. 文本事件 (表单输入触发)
- input 用户输入事件
三、事件监听
事件监听让程序检测是否有事件产生,一旦有事件触发,就立刻调用一个函数做出相应,也称为绑定事件或者注册事件,比如鼠标经过显示下拉菜单,比如点击可以播放轮播图等等
1. 语法
元素对象.addEventListener('事件类型',要执行的函数)
2. 事件监听三要素
- 事件源:哪个dom元素被事件触发了,要获取dom元素
- 事件类型:用什么方式触发,比如鼠标单击click、鼠标经过mouseover等
- 事件调用的函数:要做什么事
文本事件:
<script>
const input = document.querySelector('input')
input.addEventListener('input',function () {
console.log(input.value) //拿到用户输入文本
})
</script>
键盘事件:
<script>
const input = document.querySelector('input')
input.addEventListener('keydown',function () {
console.log('键盘按下')
})
input.addEventListener('keyup',function () {
console.log('键盘弹起')
})
</script>
焦点事件:
<script>
const input = document.querySelector('input')
input.addEventListener('focus',function () {
console.log('焦点触发')
})
input.addEventListener('blur',function () {
console.log('失去焦点触发')
})
</script>
四、环境对象
函数内部特殊的变量this,它代表当前函数运行时所处的环境 每个函数内都有 普通函数里面对象指的是window this指向调用他的对象
作用:
- 弄清楚this的指向,可以让我们代码更简洁
- 函数的调用方式不同,this的指代对象也不同
- 【谁调用,this就是谁】是判断this指向的粗略规划
- 直接调用函数,其实相当于是window.函数,所以this指代window
五、回调函数
- 如果将函数A作为参数传递给函数B时,我们称函数A为回调函数
- 简单理解:当一个函数当做参数来传递给另外一个函数的时候,这个函数就是回调函数
- 回调函数本质还是函数,只不过把它当参数使用
- 使用匿名函数作为回调函数比较常见
例:
function fn() {
console.log('我是回调函数')
//fn传递给了setInterval,fn就是回调函数
}
setInterval(fn, 1000)
六、事件流
事件流指的是事件完整执行过程中的流动路径
1. 分类
- 捕获阶段 从父到子
- 冒泡阶段 从子到父
实际工作都是使用事件冒泡为主
2. 事件捕获概念
从DOM的根元素开始去执行对应的事件(从外到里)
事件捕获需要写对应代码才能看到效果
DOM.addEventListener(事件类型,事件处理函数,是否使用捕获机制)
说明:
- DOM.addEventListener第三个参数传入true代表是捕获阶段触发(很少使用)
- 若传入false代表冒泡阶段触发,默认就是false
3. 事件冒泡概念
当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发,这一过程被称为事件冒泡
简单理解:
当一个元素触发事件后,会依次向上调用所有父级元素的同名事件
事件冒泡是默认存在的
L2事件监听第三个参数是false,或者默认都是冒泡
七、事件委托
- 优点:减少注册次数,可以提高程序性能
- 原理:利用事件冒泡的特点
- 实现:事件对象.target.tagName可以获取真正触发事件的元素
给父元素注册事件,当我们触发子元素时,会冒泡到父元素身上,从而触发父元素的事件
八、案例
1、随机点名案例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
h2 {
text-align: center;
}
.box {
width: 600px;
margin: 50px auto;
display: flex;
font-size: 25px;
line-height: 40px;
}
.qs {
width: 450px;
height: 40px;
color: red;
}
.btns {
text-align: center;
}
.btns button {
width: 120px;
height: 35px;
margin: 0 50px;
}
</style>
</head>
<!--
随机点名案例
1、点击开始按钮随机抽取数组的一个数据,放到页面中
2、点击结束按钮删除数组当前抽取的一个数据
3、当抽取到最后一个数据的时候,两个按钮同时禁用(写点开始里面,只剩最后一个数据就不用抽了)
核心:利用定时器快速展示,停止定时器结束展示
-->
<body>
<h2>随机点名</h2>
<div class="box">
<span>名字是:</span>
<div class="qs">点击开始</div>
</div>
<div class="btns">
<button class="start">开始</button>
<button class="end">结束</button>
</div>
<script>
// 局部变量在代码块执行完毕后会被销毁
// 数据数组
const arr = ['马超', '黄忠', '赵云', '关羽', '张飞']
//定义一个全局变量
let timerId = 0
let random = 0
//开始按钮
const start = document.querySelector('.start')
//点击事件
start.addEventListener('click',function () {
//随机数
timerId = setInterval( function fn(){
random = Math.floor(Math.random() * arr.length)
const qs = document.querySelector('.qs')
qs.innerHTML = `${arr[random]}`
// start.disabled = true
// end.disabled = false
},50)
//如果数组里面还有一个值了,不需要再抽取,禁用两个按钮
if (arr.length === 1) {
start.disabled = true
end.disabled = true
}
})
//关闭按钮
const end = document.querySelector('.end')
end.addEventListener('click',function () {
clearInterval(timerId)
// start.disabled = false
// end.disabled = true
//结束了可以删除当前抽取的那个数组元素
arr.splice(random,1)
console.log(arr)
})
// qs.innerHTML(`${arr[random]}`)
</script>
</body>
</html>
2、搜索框案例:
<!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>Document</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
ul {
list-style: none;
}
.mi {
position: relative;
width: 223px;
margin: 100px auto;
}
.mi input {
width: 223px;
height: 48px;
padding: 0 10px;
font-size: 14px;
line-height: 48px;
border: 1px solid #e0e0e0;
outline: none;
}
.mi .search {
border: 1px solid #ff6700;
}
.result-list {
position: absolute;
left: 0;
top: 48px;
width: 223px;
border: 1px solid #ff6700;
border-top: 0;
background: #fff;
display: none;
}
.result-list a {
display: block;
padding: 6px 15px;
font-size: 12px;
color: #424242;
text-decoration: none;
}
.result-list a:hover {
background-color: #eee;
}
</style>
</head>
<body>
<div class="mi">
<input type="search" placeholder="小米笔记本">
<ul class="result-list">
<li><a href="#">全部商品</a></li>
<li><a href="#">小米11</a></li>
<li><a href="#">小米10S</a></li>
<li><a href="#">小米笔记本</a></li>
<li><a href="#">小米手机</a></li>
<li><a href="#">黑鲨4</a></li>
<li><a href="#">空调</a></li>
</ul>
</div>
<script>
const input = document.querySelector('input')
const list = document.querySelector('.result-list')
//获得焦点
input.addEventListener('focus',function () {
list.style.display = 'block'
input.classList.add('search')
})
//失去焦点
input.addEventListener('blur',function () {
list.style.display = 'none'
input.classList.remove('search')
})
</script>
</body>
</html>
3、tab栏切换案例
<!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>tab栏切换</title>
<style>
* {
margin: 0;
padding: 0;
}
.tab {
width: 590px;
height: 340px;
margin: 20px;
border: 1px solid #e4e4e4;
}
.tab-nav {
width: 100%;
height: 60px;
line-height: 60px;
display: flex;
justify-content: space-between;
}
.tab-nav h3 {
font-size: 24px;
font-weight: normal;
margin-left: 20px;
}
.tab-nav ul {
list-style: none;
display: flex;
justify-content: flex-end;
}
.tab-nav ul li {
margin: 0 20px;
font-size: 14px;
}
.tab-nav ul li a {
text-decoration: none;
border-bottom: 2px solid transparent;
color: #333;
}
.tab-nav ul li a.active {
border-color: #e1251b;
color: #e1251b;
}
.tab-content {
padding: 0 16px;
}
.tab-content .item {
display: none;
}
.tab-content .item.active {
display: block;
}
</style>
</head>
<body>
<div class="tab">
<div class="tab-nav">
<h3>每日特价</h3>
<ul>
<li><a class="active" href="javascript:;">精选</a></li>
<li><a href="javascript:;">美食</a></li>
<li><a href="javascript:;">百货</a></li>
<li><a href="javascript:;">个护</a></li>
<li><a href="javascript:;">预告</a></li>
</ul>
</div>
<div class="tab-content">
<div class="item active"><img src="./img/tab00.png" alt="" /></div>
<div class="item"><img src="./img/tab01.png" alt="" /></div>
<div class="item"><img src="./img/tab02.png" alt="" /></div>
<div class="item"><img src="./img/tab03.png" alt="" /></div>
<div class="item"><img src="./img/tab04.png" alt="" /></div>
</div>
</div>
<!--
Tab栏切换
1、主要核心是类的切换,设定一个当前类,可以让当前元素高亮
2、鼠标经过当前选项卡,先移除其余元素身上的当前类,而只给当前元素添加类
3、当前类只能有一个
-->
<script>
//1、 a 模块制作 要给5个链接绑定鼠标经过事件
//1.1、 获取a元素
const as = document.querySelectorAll('.tab-nav a')
const items = document.querySelectorAll('.tab-content .item')
for (let i = 0; i < as.length; i++) {
as[i].addEventListener('mouseenter',function () {
// console.log('鼠标经过');
//排他思想 移除其他的active
document.querySelector('.tab-nav .active').classList.remove('active')
// 自身添加active this 当前经过的a
this.classList.add('active')
//5个大盒子
//排他思想
document.querySelector('.tab-content .active').classList.remove('active')
// 自身添加active this 当前经过的item
// items[i].classList.add('active')
document.querySelector(`.tab-content .item:nth-child(${i + 1})`).classList.add('active')
})
}
</script>
</body>
</html>