事件
什么是事件
事件:在某个特定的时机执行某段代码
事件的三个要素:
- 事件源:触发事件的那个元素
- 事件类型:触发的条件
- 事件处理函数:要做什么事情
事件监听
事件监听 是将事件处理函数注册到指定的 html 元素,当事件被触发时,事件处理函数就会被执行。 事件监听也叫事件注册、事件绑定
给一个元素添加事件监听:
元素.addEventListener(事件类型,事件处理函数)
下面是一个基本的例子:
btn.addEventListener("click", function () {
alert("我被点击了~");
});
事件处理函数是一个回调函数,只有在事件被触发时才会自动调用
事件监听的版本
L0 版本的事件监听,在同一事件源上注册了多个事件类型相同的事件时,会相互覆盖
L2 版本的事件监听,多个同名事件先后触发,不会相互覆盖,还拥有事件的更多特性,推荐使用
事件类型
鼠标事件
-
click:鼠标单击事件 -
mouseenter/mouseleave:没有冒泡的鼠标移入/移出事件 -
mouserover/mouseout:有冒泡的鼠标移入/移出事件
const box = document.querySelector(".box");
box.addEventListener("mouseenter", function () {
box.innerHTML = "mouse enter";
});
box.addEventListener("mouseleave", function () {
box.innerHTML = "mouse leave";
});
鼠标移入/移出事件只会在进入/离开元素时触发一次
键盘事件
keydown:键盘按下事件(按下不松手会一直触发)keyup:键盘抬起事件keypress:键盘按压事件
执行顺序:keydown > keypress > input > keyup
const input = document.querySelector(".search");
input.addEventListener("keydown", function () {
console.log("keydown:", input.value);
});
input.addEventListener("keypress", function () {
console.log("keypress:", input.value);
});
input.addEventListener("input", function () {
console.log("input:", input.value);
});
input.addEventListener("keyup", function () {
console.log("keyup:", input.value);
});
keydown 和 keypress 事件无法获取最后一次按键的值
我们可以在事件处理函数中使用 e.key 得到按下了哪个键
表单事件
-
focus:获得焦点事件 -
blur:失去焦点事件 -
input:用户输入事件(表单 value 值变化时触发)
eg.小米搜索框
<div class="mi">
<!-- 搜索框 -->
<input type="search" placeholder="小米笔记本" class="search-text" />
<!-- 搜索结果列表 -->
<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>
// 1.获取元素
const input = document.querySelector(".search-text");
const list = document.querySelector(".result-list");
// 2.添加焦点事件
input.addEventListener("focus", function () {
// 修改搜索框边框颜色
input.classList.add("search");
// 显示搜索结果列表
list.style.display = "block";
});
input.addEventListener("blur", function () {
input.classList.remove("search");
list.style.display = "none";
});
input.addEventListener("input", function () {
// 打印搜索框的值
console.log(input.value);
});
事件对象
事件处理函数的第一个参数就是事件对象,这个对象里有本次事件的相关信息:
e.target:获取事件源e.key:获取用户实际按下了哪个键,如 Enter、a 等
const input = document.querySelector("input");
input.addEventListener("keyup", function (e) {
console.log(e);
console.log(e.target);
console.log(e.target.tagName);
console.log(e.key);
});
事件对象的其他常见属性有:
排他思想
排他思想:先排除其他人,再突出我自己
突出显示某一个元素是排他思想的主要使用场景
<button class="pink">按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
// 需求: 点击哪个按钮,哪个按钮高亮,其余不高亮
// 先获取所有的button按钮
const btns = document.querySelectorAll('button')
// 利用循环来依次的给这5个按钮绑定点击事件
for (let i = 0; i < btns.length; i++) {
btns[i].addEventListener('click', function () {
// 排他思想
// 1. 先排除其他人,将其他按钮移除 pink 类
document.querySelector('.pink').classList.remove('pink')
// 2. 留下我自己,给自己添加 pink类
this.classList.add('pink')
})
}
eg.Tab栏切换
const as = document.querySelectorAll(".tab-nav li a");
const items = document.querySelectorAll(".tab-content .item");
// 循环给每个导航项添加事件
for (let i = 0; i < as.length; i++) {
as[i].addEventListener("mouseenter", function () {
// 利用排他思想修改元素样式
document
.querySelector(".tab-nav li .active")
.classList.remove("active");
this.classList.add("active");
// 添加active类的item会显示
document
.querySelector(".tab-content .active")
.classList.remove("active");
console.log(i);
items[i].classList.add("active");
});
}
this 指向问题
this 总是指向当前函数的调用者:
// 1.全局 this 指向 window 对象
console.log("全局this:", this);
// 2.普通函数中的 this 指向 window 对象
function fn() {
console.log("普通函数this:", this);
}
fn();
// 3.事件中的 this 指向事件源对象
const btn = document.querySelector("button");
btn.addEventListener("click", function () {
console.log("事件this:", this);
});
// 4.对象方法中的 this 指向这个对象
const cat = {
say: function () {
console.log("对象this:", this);
},
};
cat.say();
// 5.定时器中的 this 指向 window 对象
setTimeout(function () {
console.log("定时器this:", this);
}, 5000);
this:谁调用,我就指向谁
综合案例-轮播图
// 定义一个当前索引
let i = 0;
// 定义修改页面样式的函数
function change(i) {
// console.log('i:',i);
// 换图、换背景色、换文字
img.src = sliderData[i].url;
footer.style.backgroundColor = sliderData[i].color;
txt.innerHTML = sliderData[i].title;
// 换小圆点:先移除当前小圆点,再添加新的小圆点
document
.querySelector(".slider-indicator .active")
.classList.remove("active");
lis[i].classList.add("active");
}
// 1.上一张
prevBtn.addEventListener("click", function () {
i--;
i = i < 0 ? sliderData.length - 1 : i;
change(i);
});
// 2.下一张
nextBtn.addEventListener("click", function () {
i++;
i = i >= sliderData.length ? 0 : i;
change(i);
});
// 3.跳转到
for (let j = 0; j < lis.length; j++) {
lis[j].addEventListener("click", function () {
// 需要修改一下全局索引,跳转后从当前位置开始
i = j;
change(j);
});
}
// 4.自动轮播
let timer = setInterval(function () {
// 自动模拟一次用户点击事件
nextBtn.click();
}, 1000);
// 鼠标移入停止自动轮播
slider.addEventListener("mouseenter", function () {
clearInterval(timer);
});
// 鼠标移出继续自动轮播
slider.addEventListener("mouseleave", function () {
// 保险起见,先清除一下
clearInterval(timer);
// 必须使用同一个定时器timer
timer = setInterval(function () {
nextBtn.click();
}, 1000);
});