一.绑定事件的方式
1. 事件绑定介绍
DOM(Document Object Model,文档对象模型)是针对HTML文档和XML(可扩展的标记语言)文档的一个API。DOM描绘了一个层次化的节点树,允许开发人员添加、移出和修改页面的某一部分,DOM脱胎于Netscape及微软公司创始的DHTML(动态HTML)。但现在它已经成为表现和操作页面标记的真正跨平台、语言中立的方式。
Netscape Navigator 4和IE4分别发布于1997年的6月和10月发布的DHTML,由于IE4和Netscape Navigator4分别支持不同的DHTML,为了统一标准,W3C开始制定DOM。1998年10月W3C总结了IE和 Navigator4的规范,制定了DOMLevel 1即DOM1,之前IE与Netscape的规范则被称为DOMLevel 0即DOM0。
- Dom0
- Dom0级事件具有极好的跨浏览器优势,会以最快的速度绑定。
- 为某一个元素的同一个行为绑定不同的方法在行内会分别执行
- 为某一个元素的同一个行为绑定不同的方法在script标签中后面的方法会覆盖前面的方法
- 删除Dom0事件处理程序,只要将对应事件的属性设置为null即可
- Dom1
- Dom1一般只有设计规范没有具体实现,企业级应用无
- Dom2
- Dom2级事件是通过addEventListener绑定的事件,IE下的Dom2事件通过attachEvent绑定
- 可以给某个元素的同一个行为绑定不同的方法在行内会分别执行
- 删除Dom2事件处理程序通过removeEventListener
- Dom3
- Dom3级事件在Dom2级事件的基础上添加了更多的事件类型
- Dom3级事件在Dom2级事件的基础上添加了更多的事件类型
2. DOML0绑定事件
a) 高版本浏览器绑定
- 语法:
- DOM对象.onclick = function() {}
- 特点:
- 不同事件类型会依次执行
- 相同事件类型会发生覆盖
b) 低版本浏览器绑定
- 语法:
- DOM对象.onclick = function() {}
- 特点:
- 不同事件类型会依次执行
- 相同事件类型发生覆盖
c) 高版本浏览器绑定多个相同事件
- 语法:
- DOM对象.onclick = funtion() {}
- DOM对象.onclick = function() {}
d) 低版本浏览器绑定多个相同事件
- 语法:
- DOM对象.onclick = funtion() {}
- DOM对象.onclick = function() {}
e) 总结
DOMLO绑定事件高低版本浏览器之间不存在任何的差异
3. DOML0解绑事件
a) 高版本浏览器解绑事件
- 语法
- DOM对象.onclick = null
b) 低版本浏览器解绑事件
- 语法
- DOM对象.onclick = null
4. DOML2绑定事件
a) 高版本浏览器绑定事件
- 语法:
- DOM对象.addEventListener(‘事件类型’, function(){});
- DOM对象.addEventListener(‘事件类型’, 函数名);
- 特点:
- 绑定多个事件会依次执行
- 绑定多个相同事件不会覆盖
b) 低版本浏览器绑定事件
- 语法:
- DOM对象.attachEvent(‘on事件类型’, function() {})
- DOM对象.attachEvent(‘on事件类型’, 函数名)
- 特点:
- 绑定多个事件会依次执行
- 绑定多个事件不会覆盖
- 绑定事件需要加on
- 低版本浏览器不支持addEventListener
5. DOML2解绑事件
a) 高版本浏览器解绑事件
- 语法:
- 回调函数设置为命名函数
- DOM对象.removeEventListener(‘事件类型’, 函数名)
b) 低版本浏览器解绑事件
- 语法:
- 回调函数设置为命名函数
- DOM对象.detachEvent(‘on事件类型’, 函数名)
6. 课堂案例
a) 封装绑定事件兼容性
二.事件流
1. 什么是事件流?
事件流是事件在执行过程中的一种自然现象,事件流包含3部分:
- 事件冒泡
- 事件捕获
- 处理程序(事件执行的代码)
2. 事件冒泡
a) DOML0事件冒泡
<!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>
.box {
width: 300px;
height: 300px;
background-color: red;
}
.one {
width: 200px;
height: 200px;
background-color: blue;
}
</style>
</head>
<body>
<div class="box">
<div class="one"></div>
</div>
<script>
// DOML0实现冒泡
var one = document.querySelector('.one');
var box = document.querySelector('.box');
one.onclick = function() {
console.log('我是子元素被点击了');
}
box.onclick = function() {
console.log('我是父元素被点击了');
}
</script>
</body>
</html>
b) DOML2事件冒泡
<body>
<div class="box">
<div class="one"></div>
</div>
<script>
// DOML0实现冒泡
var one = document.querySelector('.one');
var box = document.querySelector('.box');
one.addEventListener('click', function() {
console.log('我是子元素被点击了');
})
box.addEventListener('click',function(){
console.log('我是父元素被点击了');
})
</script>
</body>
c) 低版本浏览器事件冒泡
<body>
<div class="box" id="box">
<div class="one" id="one"></div>
</div>
<script>
// DOML0实现冒泡
var one = document.getElementById('one');
var box = document.getElementById('box');
one.attachEvent('onclick', function() {
console.log('子元素被点击了');
})
box.attachEvent('onclick', function() {
console.log('父元素被点击了');
})
</script>
</body>
总结:
- 事件冒泡是事件流中的默认现象
- onmouseover 会触发事件冒泡
- onmouseenter 不会触发事件冒泡
3. 事件捕获
a) DOML2事件捕获
<body>
<div class="box" id="box">
<div class="one" id="one"></div>
</div>
<script>
// DOML0实现冒泡
// DOML0实现冒泡
var one = document.querySelector('.one');
var box = document.querySelector('.box');
one.addEventListener('click', function () {
console.log('我是子元素被点击了');
},true)
box.addEventListener('click', function () {
console.log('我是父元素被点击了');
},true)
</script>
</body>
注意:
- 只有高版本浏览器中DOML2方式才支持事件捕获
- DOML2方式第三个参数为true,代表事件捕获, 默认false代表事件冒泡
b) 总结
dom0事件及低级浏览器的dom2事件(没有第三个参数)都是只有冒泡,以后我们用的最多的也是冒泡,捕获几乎不用,高级浏览器的dom2事件可以根据第三个参数选择是捕获还是冒泡,一般我们都不写,默认是冒泡
4. 阻止事件冒泡
a) DOML0阻止事件冒泡
<body>
<div class="box" id="box">
<div class="one" id="one"></div>
</div>
<script>
var one = document.querySelector('.one');
var box = document.querySelector('.box');
one.onclick = function (e) {
console.log('我是子元素被点击了');
// 阻止事件冒泡
e.stopPropagation();
}
box.onclick = function (e) {
console.log('我是父元素被点击了');
// 阻止事件冒泡
e.stopPropagation();
}
</script>
</body>
b) DOML2阻止事件冒泡
<body>
<div class="box" id="box">
<div class="one" id="one"></div>
</div>
<script>
var one = document.querySelector('.one');
var box = document.querySelector('.box');
one.addEventListener('click', function (e) {
console.log('我是子元素被点击了');
// 阻止事件冒泡
e.stopPropagation();
})
box.addEventListener('click', function (e) {
console.log('我是父元素被点击了');
// 阻止事件冒泡
e.stopPropagation();
})
</script>
</body>
c) 低版本浏览器阻止事件冒泡
<body>
<div class="box" id="box">
<div class="one" id="one"></div>
</div>
<script>
var one = document.querySelector('.one');
var box = document.querySelector('.box');
one.attachEvent('onclick', function(e) {
console.log('我是子元素被点击了');
// 阻止事件冒泡
e.cancelBubble = true;
})
box.attachEvent('onclick',function (e) {
console.log('我是父元素被点击了');
// 阻止事件冒泡
e.cancelBubble = true;
})
</script>
</body>
5. 拓展-阻止标签默认行为
a) 阻止表单提交默认跳转行为
<body>
<form action="">
<input type="text" name="uname">
<input type="submit" class="btn">
</form>
<script>
var btn = document.querySelector('.btn');
btn.addEventListener('click', function(e) {
console.log(123);
// 阻止表单默认跳转
e.preventDefault();
})
</script>
</body>
b) 阻止a标签点击跳转行为
<body>
<form action="">
<input type="text" name="uname">
<input type="submit" class="btn">
</form>
<a href="">点我</a>
<script>
var a = document.querySelector('a');
a.onclick = function(e) {
console.log(123);
e.preventDefault();
// 或者
// return false;
}
</script>
</body>
C) 总结
- 低版本浏览器DOML0事件写法中,阻止a标签默认行为通过 return false实现, 不支持preventDefault()
- 低版本浏览器DOML0事件写法中,阻止表单默认行为 通过 return false 实现,不支持preventDefault()
- 低版本浏览器DOML2事件写法中,阻止a标签和表单默认行为都是通过 return false实现
三.事件委托
1.什么是事件委托
事件委托: 本质上也是一种注册事件的方式,只不过没有将事件直接注册给事件源,而是给父元素注册了事件
注意:
事件委托(事件委派)中给父元素注册事件,该父元素不一定非得是直接父元素
2.什么时候使用事件委托
- 在任何时候注册事件都可以使用事件委托
- 如果页面中元素是动态创建且注册事件,强烈推荐使用事件委托实现(事件委托的重要应用场景)
- 事件委托可以减少代码量,提高程序执行效率
3.事件委托如何使用
a) 步骤
- 给当前事件源父元素注册事件
- 通过 事件对象参数.target 获取事件源
- 操作当前事件源
b) 事件委托实现核心
<body>
<div class="box">
<input type="button" value="按钮" class="btn">
</div>
<ul>
<li>我是li标签</li>
<li>我是li标签</li>
<li>我是li标签</li>
<li>我是li标签</li>
</ul>
<script>
// 正常注册事件通过委托
var box = document.querySelector('.box');
box.addEventListener('click', function(e) {
console.log(e.target.value);
});
// 通过委托提供代码执行效率
var lis =document.querySelectorAll('li');
for(var i = 0; i < lis.length; i++) {
lis[i].addEventListener('click', function() {
console.log(this.innerHTML);
})
}
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e){
console.log(e.target.innerHTML);
})
</script>
</body>
<body>
<div class="box">
<input type="button" value="按钮" class="btn">
</div>
<ul>
<li>我是li标签</li>
<li>我是li标签</li>
<li>我是li标签</li>
<li>我是li标签</li>
</ul>
<script>
// 正常注册事件通过委托
var box = document.querySelector('.box');
box.addEventListener('click', function(e) {
console.log(e.target.value);
});
// 通过委托提供代码执行效率
var lis =document.querySelectorAll('li');
for(var i = 0; i < lis.length; i++) {
lis[i].addEventListener('click', function() {
console.log(this.innerHTML);
})
}
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e){
console.log(e.target.innerHTML);
})
</script>
</body>
<body>
<div class="box">
<input type="button" value="按钮" class="btn">
</div>
<ul>
<li>我是li标签</li>
<li>我是li标签</li>
<li>我是li标签</li>
<li>我是li标签</li>
</ul>
<script>
// 正常注册事件通过委托
var box = document.querySelector('.box');
box.addEventListener('click', function(e) {
console.log(e.target.value);
});
// 通过委托提供代码执行效率
var lis =document.querySelectorAll('li');
for(var i = 0; i < lis.length; i++) {
lis[i].addEventListener('click', function() {
console.log(this.innerHTML);
})
}
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e){
console.log(e.target.innerHTML);
})
</script>
</body>
<body>
<div class="box">
<input type="button" value="按钮" class="btn">
</div>
<ul>
<li>我是li标签</li>
<li>我是li标签</li>
<li>我是li标签</li>
<li>我是li标签</li>
</ul>
<script>
// 正常注册事件通过委托
var box = document.querySelector('.box');
box.addEventListener('click', function(e) {
console.log(e.target.value);
});
// 通过委托提供代码执行效率
var lis =document.querySelectorAll('li');
for(var i = 0; i < lis.length; i++) {
lis[i].addEventListener('click', function() {
console.log(this.innerHTML);
})
}
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e){
console.log(e.target.innerHTML);
})
</script>
</body>
<body>
<div class="box">
<input type="button" value="按钮" class="btn">
</div>
<ul>
<li>我是li标签</li>
<li>我是li标签</li>
<li>我是li标签</li>
<li>我是li标签</li>
</ul>
<script>
// 正常注册事件通过委托
var box = document.querySelector('.box');
box.addEventListener('click', function(e) {
console.log(e.target.value);
});
// 通过委托提供代码执行效率
var lis =document.querySelectorAll('li');
for(var i = 0; i < lis.length; i++) {
lis[i].addEventListener('click', function() {
console.log(this.innerHTML);
})
}
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e){
console.log(e.target.innerHTML);
})
</script>
</body>
<script>
// 正常注册事件通过委托
var box = document.querySelector('.box');
box.addEventListener('click', function(e) {
console.log(e.target.value);
});
// 通过委托提供代码执行效率
var lis =document.querySelectorAll('li');
for(var i = 0; i < lis.length; i++) {
lis[i].addEventListener('click', function() {
console.log(this.innerHTML);
})
}
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e){
console.log(e.target.innerHTML);
})
</script>
c) 代码演示
<script>
// 正常注册事件通过委托
var box = document.querySelector('.box');
box.addEventListener('click', function(e) {
console.log(e.target.value);
});
// 通过委托提供代码执行效率
var lis =document.querySelectorAll('li');
for(var i = 0; i < lis.length; i++) {
lis[i].addEventListener('click', function() {
console.log(this.innerHTML);
})
}
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e){
console.log(e.target.innerHTML);
})
</script>
d) 注意事项
- 事件委托中需要重点理解 事件对象参数.target
- 事件对象参数.target 获取到的事件对象是用户实际点击的标签对象
- 事件对象参数.target 得到的是一个具体的DOM标签对象
- 一般在事件委托中,不会直接操作 事件对象参数.target,一般都加一个判断条件,确认用户点击的就是正确的标签,判断条件一般都通过标签名判断 **DOM对象.nodeName **
4.动画事件
webkitAnimationEnd 动画完成后执行的事件
webkitTransitionEnd 过渡动画执行完成后的事件