目录
一、事件注册
1.1、传统注册方式
<button onclick="console.log('haha,骗你的。。。')">点我有奖</button>
(2)通过DOM对象指定的属性来绑定
<button id="btn">点我。。</button>
<script>
var btn = document.querySelector('#btn');
btn.onclick = function() {
console.log('谢谢。。。。')
};
</script>
1.2、监听注册方式
另一种方式比较特殊事件注册方式是通过事件监听来注册,称为设置事件监听器,它是 W3C 标准推荐使用的方式。通过 EventTarget.addEventListener() 方法来实现。
target.addEventListener(type, listener, useCapture);
<button>点击</button>
<script>
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
console.log('大家周末好!');
});
</script>
1.3、两种注册方式比较
(1)如果使用传统方式进行注册,当对同一个对象添加相同事件时,后面的事件会覆盖掉前面的事件;如果使用监听方式进行注册,当同一个对象绑定相同多个事件时,这些事件都会被执行。
(2)传统注册方式只能进行冒泡,不能进行捕获;而监听注册方式可以冒泡也可以捕获。
示例:
<button class="btn1">传统注册</button>
<button class="btn2">监听注册</button>
<script>
var btn1 = document.querySelector('.btn1');
var btn2 = document.querySelector('.btn2');
// 传统注册
btn1.onclick = function () {
console.log('明天星期一,我们休息,大家可以睡个懒觉,哈哈');
};
btn1.onclick = function () {
console.log('星期二我们继续');
};
// 监听注册
btn2.addEventListener('click', function () {
console.log('今天星期天,快下课了,哈哈');
});
btn2.addEventListener('click', function () {
console.log('但是还得花时间来消化今天的内容。');
});
</script>
二、解绑事件
eventTarget.事件类型 = null;
eventTarget.removeEventListener(type, listener[, useCapture]);
<button class="btn1">传统注册</button>
<button class="btn2">监听注册</button>
<script>
var btn1 = document.querySelector('.btn1');
var btn2 = document.querySelector('.btn2');
// 传统注册
btn1.onclick = function() {
console.log('明天星期一,我们休息,大家可以睡个懒觉,哈哈');
};
// 解绑事件
btn1.onclick = null;
// 监听注册
/*不能解绑事件
btn2.addEventListener('click', function () {
console.log('今天星期天,快下课了,哈哈');
});
btn2.removeEventListener('click', function () {
console.log('我们没有关系了。')
});*/
function fn() {
console.log('今天星期天,快下课了,哈哈');
btn2.removeEventListener('click', fn);
}
btn2.addEventListener('click', fn);
</script>
注意:
对于传统注册事件的解绑:
(1)将解绑事件写在函数里的任何位置,其注册事件只会执行一次;
(2)将解绑事件写在函数外的注册事件前,解绑事件对其无效;将解绑事件写在函数外的注册事件后,注册事件将不执行。
对于监听注册事件的解绑:
(1)将解绑事件写在函数里的任何位置,其注册事件只会执行一次;
(2)将解绑事件写在函数外,那么注册的事件将无效。
(3)对于监听注册方式的解绑,需要注意事件类型和监听函数必须是相同的,否则解绑无效。
三、事件流
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件流</title>
<style>
.outer {
overflow: hidden;
width: 300px;
height: 300px;
margin: 100px auto;
background-color: blueviolet;
text-align: center;
}
.inner {
width: 200px;
height: 200px;
margin: 50px;
background-color: cornflowerblue;
line-height: 200px;
color: #fff;
}
</style>
</head>
<body>
<div class="outer">
<div class="inner">内部盒子</div>
</div>
<script>
var inner = document.querySelector('.inner');
var outer = document.querySelector('.outer');
inner.addEventListener('click', function () {
console.log('inner');
});
outer.addEventListener('click', function () {
console.log('outer');
});
// 给 body 添加点击事件
document.body.addEventListener('click', function () {
console.log('body');
});
// 给 html 添加点击事件
document.documentElement.addEventListener('click', function () {
console.log('html');
});
// 给 document 添加点击事件
document.addEventListener('click', function () {
console.log('document');
});
window.addEventListener('click', function () {
console.log('window');
});
</script>
</body>
</html>
注意:
(1)JavaScript 代码中只能执行捕获或冒泡其中一个阶段,要么冒泡,要么捕获。
(2)onclick 与 attachEvent 方式注册的事件只有冒泡阶段。
(3)addEventListener(type, listener[, useCapture]) 第三个参数为 true 表示捕获阶段,默认空着或者 false 为冒泡阶段。
3.1、事件冒泡
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件冒泡</title>
<style>
.box {
width: 200px;
height: 200px;
background-color: red;
}
</style>
</head>
<body>
<div class="box"></div>
<script>
var box = document.querySelector('.box')
box.addEventListener('click', function () {
console.log("div")
});
document.body.addEventListener('click', function () {
console.log('body');
});
document.documentElement.addEventListener('click', function () {
console.log('html');
});
</script>
</body>
</html>
运行结果:
注意:事件冒泡是从目标对象向上传播。
3.2、事件捕获
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件捕获</title>
<style>
.box {
width: 200px;
height: 200px;
background-color: red;
}
</style>
</head>
<body>
<div class="box"></div>
<script>
var box = document.querySelector('.box')
box.addEventListener('click', function() {
console.log("div")
}, true);
document.body.addEventListener('click', function() {
console.log('body');
}, true);
document.documentElement.addEventListener('click', function() {
console.log('html');
}, true);
</script>
</body>
</html>
运行结果:
四、事件对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件对象</title>
</head>
<body>
<ul>
<li>1</li>
<li>2</li>
</ul>
<script>
var ul = document.querySelector('ul');
ul.addEventListener('click', function(event) {
// 处理兼容性问题
event = event || window.event;
console.log(event);
// 从事件对象 event 中获取目标对象
console.log(event.target.innerHTML);
});
</script>
</body>
</html>
五、事件属性
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件对象属性</title>
<style>
.box {
width: 100px;
height: 100px;
background-color: #ff6700;
}
</style>
</head>
<body>
<div class="box"></div>
<script>
var box = document.querySelector('.box')
box.onclick = function (event) {
event = event || window.event;
// 1. 获取目标对象
// 1.1 target 标准
console.log(event.target)
// 1.2 srcElement 非标准
console.log(event.srcElement);
// 2. 获取事件类型,不带 on
console.log(event.type);
// 3. 获取在可视化区域的坐标
console.log(event.clientX + ', ' + event.clientY);
};
</script>
</body>
</html>
5.1事件目标
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件对象目标</title>
<style>
ul,li {
list-style: none;
}
.item {
width: 100px;
height: 50px;
background-color: #ff6700;
margin: 10px;
text-align: center;
line-height: 50px;
color: white;
}
</style>
</head>
<body>
<ul id="box">
<li class="item">1</li>
<li class="item">2</li>
</ul>
<script>
var box = document.querySelector('#box')
box.onclick = function (event) {
event = event || window.event;
console.log(event.target);
console.log(event.srcElement);
console.log(event.currentTarget);
console.log(this);
};
</script>
</body>
</html>
说明:
(1)currentTarget:返回的是绑定事件的对象 ;
(2)target:返回的是事件的实际目标对象(IE8不支持);
5.2、事件委托
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件委托</title>
<style>
* {
padding: 0;
margin: 0;
}
ul {
list-style: none;
overflow: hidden;
margin-top: 80px;
}
ul li {
float: left;
width: 100px;
height: 30px;
text-align: center;
line-height: 30px;
color: #fff;
background-color: #000;
margin: 0 10px
}
</style>
</head>
<body>
<ul id="box">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
var ul = document.querySelector('#box')
/*
var lis = document.querySelectorAll('li')
for (var i = 0; i < lis.length; i++) {
lis[i].onmouseover = function () {
this.style.backgroundColor = 'blue';
};
lis[i].onmouseout = function () {
this.style.backgroundColor = 'black';
};
}*/
//利用事件委托
ul.onmouseover = function(e) {
console.log(e);
if (e.target.nodeName.toLowerCase() === 'li') {
e.target.style.backgroundColor = 'blue';
}
};
ul.onmouseout = function(e) {
if (e.target.nodeName.toLowerCase() === 'li') {
e.target.style.backgroundColor = 'black';
}
};
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件委托</title>
<style>
* {
padding: 0;
margin: 0;
}
ul {
list-style: none;
overflow: hidden;
margin-top: 80px;
}
ul li {
float: left;
width: 100px;
height: 30px;
text-align: center;
line-height: 30px;
color: #fff;
background-color: #000;
margin: 0 10px
}
</style>
</head>
<body>
<ul id="box">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
var ul = document.querySelector('#box')
/*
var lis = document.querySelectorAll('li')
for (var i = 0; i < lis.length; i++) {
lis[i].onmouseover = function () {
this.style.backgroundColor = 'blue';
};
lis[i].onmouseout = function () {
this.style.backgroundColor = 'black';
};
}*/
//利用事件委托
ul.onmouseover = function(e) {
console.log(e);
if (e.target.nodeName.toLowerCase() === 'li') {
e.target.style.backgroundColor = 'blue';
}
};
ul.onmouseout = function(e) {
if (e.target.nodeName.toLowerCase() === 'li') {
e.target.style.backgroundColor = 'black';
}
};
var li = document.createElement('li');
li.innerHTML = '6';
ul.append(li);
</script>
</body>
</html>
六、事件方法
6.1、阻止事件冒泡
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>阻止事件冒泡</title>
<style>
.outer {
overflow: hidden;
width: 300px;
height: 300px;
margin: 100px auto;
background-color: blueviolet;
text-align: center;
position: relative;
}
.inner {
width: 200px;
height: 200px;
margin: 50px;
background-color: cornflowerblue;
line-height: 200px;
color: #fff;
}
</style>
</head>
<body>
<div class="outer">
<div class="inner">内部盒子</div>
</div>
<script>
var inner = document.querySelector('.inner');
var outer = document.querySelector('.outer');
// 当点击 inner 时,不要触发外部的 div 的点击事件
inner.onclick = function (event) {
console.log('inner')
// 处理兼容性问题
if (event.stopPropagation()) {
event.stopPropagation(); // 这个方法早期IE版本不支持
} else {
event.cancelBubble = true; // IE支持的
}
};
outer.addEventListener('click', function (event) {
console.log('outer');
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>阻止事件冒泡</title>
<style>
.outer {
overflow: hidden;
width: 300px;
height: 300px;
margin: 100px auto;
background-color: blueviolet;
text-align: center;
position: relative;
}
.inner {
width: 200px;
height: 200px;
margin: 50px;
background-color: cornflowerblue;
line-height: 200px;
color: #fff;
}
.outer a {
position: absolute;
bottom: 5px;
left: 10px;
color: white;
text-decoration: none;
}
</style>
</head>
<body>
<div class="outer">
<div class="inner">内部盒子</div>
<a href="javascript:void(0)">点击</a>
</div>
<script>
var inner = document.querySelector('.inner');
var outer = document.querySelector('.outer');
var a = document.querySelector('a');
// 当点击 inner 时,不要触发外部的 div 的点击事件
inner.onclick = function (event) {
console.log('inner')
// 处理兼容性问题
if (event.stopPropagation()) {
event.stopPropagation(); // 这个方法早期IE版本不支持
} else {
event.cancelBubble = true; // IE支持的
}
};
outer.addEventListener('click', function (event) {
console.log('outer');
});
a.addEventListener('click', function (event) {
console.log('-----')
//event.stopPropagation();
event.stopImmediatePropagation();
});
</script>
</body>
</html>
stopPropagation()与stopImmediatePropagation()
相同点:都能阻止事件冒泡的发生。
区别:
(1)stopPropagation() 方法只能阻止事件冒泡的发生,不能阻止同一个对象的相同事件的执行。
6.2、阻止默认行为
6.2.1、阻止链接的默认行为
<a href="javascript:void(0)">淘宝</a>
<a href="javascript:;">腾讯</a>
<a href="https://www.baidu.com">百度</a>
<script>
var as = document.querySelectorAll('a');
as[2].onclick = function(event) {
//console.log(event);
event.preventDefault();
};
</script>
6.2.2、阻止提交按钮提交表单的默认行为
<p>
<form action="https://www.baidu.com" method="post">
<input type="text" name="s">
<input type="submit" value="提供">
</form>
</p>
<script>
var form = document.querySelector('form');
form.addEventListener('submit', function(event) {
event.preventDefault();
});
</script>
七、鼠标事件
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>鼠标事件</title>
<style>
*{
padding: 0;
margin: 0;
}
body {
height: 2000px;
}
.box {
position: fixed;
top: 0;
left: 0;
width: 300px;
height: 300px;
margin: 50px;
background-color: #ff6700;
}
</style>
</head>
<body>
<div class="box"></div>
<script>
var box = document.querySelector('.box')
box.addEventListener('click', function (event) {
event = event || window.event;
// client 是针对于可视化区域的
console.log(event.clientX, event.clientY);
// page 是针对于页面
console.log(event.pageX, event.pageY)
// screen 是针对于电脑屏幕
console.log(event.screenX, event.screenY);
});
</script>
</body>
</html>