目录
一、事件绑定的方式
1.句柄式写法 :只能绑定一个事件处理函数
<style>
.box {
width: 200px;
height: 200px;
background-color: green;
}
.active {
background-color: red;
}
</style>
<div class="box active"></div>
<script>
let box = document.querySelector('.box');
// 1.句柄式写法 只能绑定一个事件处理函数
document.querySelector('.box').onclick = changeBack
function changeBack() {
box.classList.contains('active') ? box.classList.remove('active') : box.classList.add('active');
}
</script>
2.addEventListener: 可以绑定多个事件处理函数
<style>
.box {
width: 200px;
height: 200px;
background-color: green;
}
.active {
background-color: red;
}
</style>
<div class="box active"></div>
<script>
// 2.addEventListener 可以绑定多个事件处理函数
let box = document.querySelector('.box');
function changeBack() {
box.classList.contains('active') ? box.classList.remove('active') : box.classList.add('active');
}
function changeContent() {
box.innerHTML ? box.innerHTML = '' : box.innerHTML = '新增内容';
}
box.addEventListener('click', changeBack);
box.addEventListener('click', changeContent);
</script>
二、事件解除
1.句柄式的事件解除:element.onclick = false;
<style>
.yhq {
width: 300px;
height: 100px;
border-radius: 24px;
background-color: coral;
color: #FFF;
text-align: center;
line-height: 100px;
}
</style>
<div class="yhq">大额优惠券</div>
<script>
let yhq = document.querySelector('.yhq');
function getyhq() {
alert("领取成功");
yhq.style.opacity = 0.5;
// 解除绑定事件
yhq.onclick = false;
}
yhq.onclick = getyhq; // 赋值函数不加小括号
</script>
2.事件监听器的解除方式 :element.removeEventListener('事件类型', 事件处理函数);
<style>
.yhq {
width: 300px;
height: 100px;
border-radius: 24px;
background-color: coral;
color: #FFF;
text-align: center;
line-height: 100px;
}
</style>
<div class="yhq">大额优惠券</div>
<script>
let yhq = document.querySelector('.yhq');
function getyhq() {
alert("领取成功");
yhq.style.opacity = 0.5;
// 解除绑定事件
yhq.removeEventListener('click', getyhq);
}
yhq.addEventListener('click', getyhq); // 函数不加小括号
</script>
三、event对象
event对象:盒子被触发时的事件, 如鼠标移动事件、键盘按下事件
鼠标even事件常用属性:
属性 | 含义 |
clientX | 盒子触发时离左边的距离(可视区域) |
clientY | 盒子触发时离顶部的距离(可视区域) |
offsetX | 盒子触发时离盒子左边的距离 |
offsetY | 盒子触发时离盒子顶部的距离 |
pageX | 盒子触发时离界面左边的距离 |
pageY | 盒子触发时离界面顶部的距离 |
screenX | 盒子触发时离屏幕左边的距离 |
screenY | 盒子触发时离屏幕顶部的距离 |
对以上even事件属性的解释:
鼠标点击红圈中绿点的地方
css:
<style>
div {
width: 200px;
height: 200px;
background-color: pink;
margin: 100px;
}
</style>
html:
<div></div>
js:
<script>
let div = document.querySelector("div");
div.onclick = function(e) {
console.log(e);
/*
clientX: 185
clientY: 120
offsetX: 78
offsetY: 21
screenX: 234
screenY: 224
*/
}
</script>
【案例】盒子上下左右移动
<style>
.box {
width: 300px;
height: 300px;
border-radius: 24px;
background-color: coral;
color: #FFF;
text-align: center;
line-height: 100px;
position: relative;
}
</style>
<div class="box"></div>
<script>
let box = document.querySelector('.box');
window.addEventListener('keydown', function(event) {
// console.log(event);
if (event.key == 'ArrowUp') {
box.style.top = parseFloat(getComputedStyle(box).top) - 3 + 'px';
}
if (event.key == 'ArrowDown') {
box.style.top = parseFloat(getComputedStyle(box).top) + 3 + 'px';
}
if (event.key == 'ArrowLeft') {
box.style.left = parseFloat(getComputedStyle(box).left) - 3 + 'px';
}
if (event.key == 'ArrowRight') {
box.style.left = parseFloat(getComputedStyle(box).left) + 3 + 'px';
}
})
</script>
四、事件响应链
1.事件冒泡:标签之间形成嵌套关系之后,绑定同一事件,会由子级逐渐冒泡到父级
<style>
.outer {
width: 300px;
height: 300px;
background-color: purple;
position: relative;
}
.middle {
width: 200px;
height: 200px;
background-color: red;
position: absolute;
left: 360px;
}
.inner {
width: 100px;
height: 100px;
background-color: green;
position: absolute;
left: 360px;
}
</style>
<div class="outer">
<div class="middle">
<div class="inner"></div>
</div>
</div>
<script>
let outer = document.querySelector('.outer');
let middle = document.querySelector('.middle');
let inner = document.querySelector('.inner');
function handleOuter() {
console.log('outer');
}
function handleMiddle() {
console.log('middle');
}
function handleInner() {
console.log('inner');
}
// 按照事件冒泡响应过程来触发
outer.onclick = handleOuter;
middle.onclick = handleMiddle;
inner.onclick = handleInner;
</script>
2.事件捕获:标签之间形成嵌套关系之后,绑定同一事件,会由父级逐渐冒泡到子级
- 格式:node.addEventListener('事件类型', 处理函数, true);
- 只有addEventListener绑定的事件才有事件捕获
<style>
.outer {
width: 300px;
height: 300px;
background-color: purple;
position: relative;
}
.middle {
width: 200px;
height: 200px;
background-color: red;
position: absolute;
left: 360px;
}
.inner {
width: 100px;
height: 100px;
background-color: green;
position: absolute;
left: 360px;
}
</style>
<div class="outer">
<div class="middle">
<div class="inner"></div>
</div>
</div>
<script>
let outer = document.querySelector('.outer');
let middle = document.querySelector('.middle');
let inner = document.querySelector('.inner');
function handleOuter() {
console.log('outer');
}
function handleMiddle() {
console.log('middle');
}
function handleInner() {
console.log('inner');
}
// 按照事件捕获响应过程来触发
outer.addEventListener('click', handleOuter, true);
middle.addEventListener('click', handleMiddle, true);
inner.addEventListener('click', handleInner, true);
</script>
3.如果既有事件冒泡也有事件捕获,就会先捕获再冒泡!!
<style>
.outer {
width: 300px;
height: 300px;
background-color: purple;
position: relative;
}
.middle {
width: 200px;
height: 200px;
background-color: red;
position: absolute;
left: 360px;
}
.inner {
width: 100px;
height: 100px;
background-color: green;
position: absolute;
left: 360px;
}
</style>
<div class="outer">
<div class="middle">
<div class="inner"></div>
</div>
</div>
<script>
let outer = document.querySelector('.outer');
let middle = document.querySelector('.middle');
let inner = document.querySelector('.inner');
function handleOuter() {
console.log('outer');
}
function handleMiddle() {
console.log('middle');
}
function handleInner() {
console.log('inner');
}
// 按照事件冒泡响应过程来触发
outer.onclick = handleOuter;
middle.onclick = handleMiddle;
inner.onclick = handleInner;
// 按照事件捕获响应过程来触发
outer.addEventListener('click', handleOuter, true);
middle.addEventListener('click', handleMiddle, true);
inner.addEventListener('click', handleInner, true);
</script>
五、事件代理
事件代理:借助事件冒泡处理过程,并且通过事件源对象获取事件目标,将事件绑定到父节点身上
【案例】通过给ul绑定事件,点击某个li时,该li的样式改变
<ul>
<li>列表标签1</li>
<li>列表标签2</li>
<li>列表标签3</li>
<li>列表标签4</li>
<li>列表标签5</li>
</ul>
<script>
let ul = document.querySelector("ul");
let lis = document.querySelectorAll('li');
// 新增一个字节点
let li = document.createElement("li");
li.innerHTML = '列表标签6';
ul.append(li);
// 给ul绑定
ul.addEventListener('click', function(event) {
// 排他思想 点击li之前去掉其他li的样式
for (let i = 0; i < lis.length; i++) {
lis[i].style.color = '';
lis[i].style.fontSize = '';
}
event.target.style.color = 'red';
event.target.style.fontSize = '24px';
// console.log(event.target);
})
</script>
结果:
六、停止冒泡
1.停止冒泡:点击子级之后,父级不再被触发
2.停止冒泡的方式:
- event.stopPropagation();
- event.cancelBubble = true
兼容性比较好的一种写法:
event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true;
<style>
.outer {
width: 300px;
height: 300px;
background-color: purple;
position: relative;
}
.middle {
width: 200px;
height: 200px;
background-color: red;
position: absolute;
left: 360px;
}
.inner {
width: 100px;
height: 100px;
background-color: green;
position: absolute;
left: 360px;
}
.box {
width: 140px;
height: 220px;
background-color: lightsalmon;
display: none;
position: absolute;
}
</style>
<div class="outer">
<div class="middle">
<div class="inner"></div>
</div>
</div>
<script>
let outer = document.querySelector('.outer');
let inner = document.querySelector('.inner');
function handleOuter() {
console.log('outer');
}
function handleInner() {
console.log('inner');
// event.stopPropagation();
// 兼容性比较好的一种写法
event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true;
}
outer.onclick = handleOuter;
inner.onclick = handleInner;
</script>
3.阻止默认事件
【案例】点击鼠标右键,弹出自己写的盒子
<style>
.box {
width: 140px;
height: 220px;
background-color: lightsalmon;
display: none;
position: absolute;
}
</style>
<div class="box">
……………………
</div>
window.oncontextmenu = function (event) {
document.querySelector(".box").style.display = "block"
document.querySelector(".box").style.top = event.pageY + "px";
document.querySelector(".box").style.left = event.pageX + "px";
return false;
}