多个事件的绑定
-
DOM对象.addEventListener(类型,事件处理函数,是否冒泡)
类型:
表示监听事件类型的字符串。事件处理函数:
当这个事件处理的时候的操作是否支持冒泡:
当设为true 时,沿着DOM树向上冒泡的事件,不会触发事件。当一个元素嵌套了另一个元素,并且两个元素都对同一事件注册了一个处理函数时,所发生的事件冒泡和事件捕获是两种不同的事件传播方式。注意:
有兼容性问题,在IE9以后的版本才支持,老版本浏览器只支持attachEvent(). -
DOM对象.attachEvent(‘on’ + 事件名称, 事件处理函数)
注意:
IE9之前用这个
处理兼容性代码
function addEventListener(element, event, fn) {
//如果没有这个属性默认是undefined
if(element.addEventListener) {
// 默认冒泡
element.addEventListener(event, fn);
} else {
element.attachEvent('on' + event, fn);
}
}
移除事件
// 第一种方式的移除事件
var btn = document.getElementById('btn');
btn.onclick = function () {
console.log('hello');
// 移除事件
btn.onclick = null;
}
// 第二种方式的移除事件
btn.addEventListener('click', fn, fasle);
// 移除事件,如果想移除事件,那么绑定事件的时候不能使用匿名函数
btn.removeEventListener('click', fn);
function fn () {
console.log('hello');
}
// 第三种方式的移除事件,attach意思是附加,detach意思是分离
btn.attachEvent('onclick', fn);
// 移除事件,如果想移除事件,那么绑定事件的时候不能使用匿名函数
btn.detachEvent('onclick', fn);
function fn () {
console.log('hello');
}
处理兼容性代码
function removeEventListener(element, event, fn) {
//如果没有这个属性默认是undefined
if(element.removeEventListener) {
// 默认冒泡
element.removeEventListener(event, fn);
} else {
element.detachEvent('on' + event, fn);
}
}
事件冒泡
事件冒泡简介
addEventListener 的第三个参数为false的时候为事件冒泡,当参数为true的时候为事件捕获
事件冒泡:会从最内层一层一层冒到最外层的元素
事件捕获:会从最外层一层一层到最内层元素
事件的三个阶段
1. 捕获阶段
2. 执行当前点击的元素
3. 冒泡阶段
HTML代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>事件冒泡</title>
<style>
div{
padding: 20px;
background-color: aliceblue;
}
#div2{
background-color: red;
}
#div3{
background-color: blue;
}
</style>
</head>
<body>
<div id="div1">
<div id="div2">
<div id="div3"></div>
</div>
</div>
</body>
</html>
JavaScript代码如下
// 此时为事件冒泡
var arr = [div1, div2, div3];
for (var i = 0; i < arr.length; i++) {
arr[i].addEventListener('click', function () {
console.log(this.id);
}, false);
}
// 输出结果 : div3 div2 div1
// 此时为事件捕获
var arr = [div1, div2, div3];
for (var i = 0; i < arr.length; i++) {
arr[i].addEventListener('click', function () {
console.log(this.id);
}, true);
}
// 输出结果 : div1 div2 div3
事件冒泡注意的地方
onlick和attachEvent这两个绑定的方式,不能设置事件捕获,只能用默认的事件冒泡。
事件冒泡的作用(事件委托)
- e.target :是真正触发事件的对象。
- e.currentTarget:代表this
案例
<!-- 单击li背景色变红 -->
<ul id="ul">
<li>001</li>
<li>002</li>
<li>003</li>
<li>004</li>
</ul>
ul.addEventListener('click', function (e) {
e.target.style.background = 'red';
}, false);
事件对象
事件对象简介
通过事件对象,可以获取到事件发生的时候喝事件相关的一些数据
var btn = document.getElementById('btn');
btn.onclick = function (e) {
// DOM标准中,是给事件处理函数一个参数
// e就是事件对象
// 在老版本的IE中获取事件对象的方式 window.event
e = e || windown.event; // 处理浏览器兼容问题
}
事件对象的属性和方法
1. e.eventPhase(了解)
- 1捕获阶段
- 2目标阶段
- 3冒泡阶段
2. e.target
- 获取真正触发事件的对象
浏览器兼容问题,在老版本IE中指的是srcElement
- 处理兼容:
var target = target || srcElement
3. e.currentTarget
- 指this(事件处理函数所属的对象)
**4.e.type **
-
获取事件名称
//优势,可以根据不同的事件名称做不同的事情,节省代码。 box.onclick = fn; box.onmouseover = fn; box.onmouseout = fn; function fn(e) { e = e || window.event; switch (e.type) { case 'click': console.log('点击box'); break; case 'mouseover': console.log('鼠标经过box'); break; case 'mouseout': console.log('鼠标离开box'); break; } }
5. e.clientX 、e.clientY
-
获取的鼠标在浏览器可视区域的坐标
注意:是相对于可视区的坐标值,原点在可视区的左上角
6. e.pageX 、e.pageY(有兼容性问题,IE9之后支持)
-
相对于整个页面的坐标
var img = document.getElementsByTagName('img'); document.onmousemove = function (e) { var e = e || window.event; // 当有滚动条的时候,必须用pageX(相对于页面的坐标值) img[0].style.left = e.pageX + 'px'; img[0].style.top = e.pageY + 'px'; }
处理兼容性问题:pageX = clientX + 页面滚动出去的距离
function getPage(e) { var pageX = e.pageX || e.clientX + getScroll().scrollLeft; var pageY = e.pageX || e.clientY + getScroll().scrollTop; return { pageX:pageX, pageY:pageY } }
-
页面滚动出去的距离
-
谷歌浏览器
- document.body.scrollLeft 横向距离
- document.body.scrollTop 纵向距离
-
有些浏览器
-
document.documentElement.scrollLeft 横向距离
-
document.documentElement.scrollTop 纵向距离
document.documentElement获取的是html
-
-
处理滚动距离的兼容性
function getScroll() { // 如果获取不到那么他的值为0,这样就可以用 ||运算符来进行处理兼容 var scrollLeft = document.body.scrollLeft || document.documentElement.scrollLeft; var scrollTop = document.body.scrollTop || document.documentElement.scrollTop; }
-
-
例题(获取盒子在页面上的位置)
- offsetLeft:横向偏移
- offsetTop:纵向偏移
7. e.preventDefault()方法(有兼容性问题)
-
取消默认行为
-
处理兼容性问题
if (e.preventDefault) { // 如果她不存在返回undefined e.preventDefault(); } else { e.returnValue = false; // ie老版本中处理默认行为 } // 推荐使用return false来处理默认行为
8. e.stopPropagation()方法 (有兼容性问题)
-
阻止冒泡
-
处理兼容性问题
if (e.stopPropagation) { // 如果她不存在返回undefined e.stopPropagation(); } else { e.cancelBubble = true; // ie老版本中处理默认行为 }
9. e.keyCode
-
获取键盘按键的编码
A:65
a:97
// 键盘事件 // keydown 键盘按下的时候 // keyup 键盘弹起的时候 // keydown 和 keyup的区别 keydown的时候我们所按的键还没有落入文本框 // keyup键盘弹起的时候按的键已经落入文本框 var txt = document.getElementById('txt'); txt.onkeydown = function (e) { // 判断当前用户按下的键是否是数字 e = e || window.event; // 如果e.keyCode 的值在 48-57 是数字 // e.keyCode 键盘码 // console.log(e.keyCode); // 按下后退键 8,删除一个字符 if ((e.keyCode < 48 || e.keyCode > 57) && e.keyCode !== 8) { // 非数字 // 取消默认行为 e.preventDefault(); // return false; 如果用return false 取消默认行为那么后续的代码将不会再执行 } }