JS事件
感谢:尚硅谷李立超老师的讲解
事件对象
当事件的响应函数被触发时,浏览器每次都会将一个事件对象实参 传递进响应函数,可以通过arguments[0]获取,也可以定义一个形参
在事件中对象中封装了当前事件相关的一切信息,比如,鼠标的坐标,键盘哪个按键被按下,鼠标滚轮滚动的方向
在ie8中,响应函数被触发时,浏览器不会传递事件对象,在ie8及以下的浏览器中,是将事件对象作为window对象的属性保存的
所以为解决事件对象的兼容性通常写做 :event = event||window.event;
<!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>
</head>
<body>
<script>
window.onclick = function (event) {
console.log(arguments[0]);
console.log(event);
//ie8 中不会传递实参对象,因为ie中event是window的一个属性,所以e可能为undefined,兼容ie8及以下浏览器
event = event || window.event;
}
</script>
</body>
</html>
事件的冒泡
所谓的冒泡指的就是事件的向上传导,当后代元素上的事件被触发时,其祖先元素的相同事件也会被触发
在开发中大部分情况下的冒泡都是有用的.如果不希望发生事件冒泡可以通过事件对象来取消冒泡
event = event || window.event;
event.cancelBubble = true;//已废弃
event.stopPropagation();//建议使用
事件的委派
- 指将事件统一绑定给元素的共同祖先元素,这样当后代元素上的事件触发时,会一直冒泡到祖先元素,从而通过祖先元素的响应函数来处理事件
- 事件委派是利用了冒泡,通过委派可以减少事件绑定的次数,提高程序的性能
事件的绑定
var btn = document.getElementById("btn");
btn.onclick = function(){
console.log("点击了btn")
}
addEventListener()
-
通过该方法也可以为事件对象绑定响应函数
-
参数:
事件的字符串,不要on
回调函数,当事件触发时该函数会被调用
是否在捕获阶段触发事件,需要一个布尔值,一般都是false
使用
addEnventListener()
可以同时为一个元素的相同事件同时绑定多个响应函数,这样当事件被触发时,响应函数将会按照绑定顺序依次执行这个方法不支持IE8及以下的浏览器
-
<!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 type="text/css">
</style>
</head>
<body>
<button id="btn">按钮</button>
<script>
var btn = document.getElementById("btn");
btn.addEventListener("click", function () {
console.log(1)
}, false)
btn.addEventListener("click", function () {
console.log(2)
}, false)
btn.addEventListener("click", function () {
console.log(3)
}, false)
</script>
</body>
</html>
attachEvent()
- 在IE8中可以使用
attchEvent()
来绑定事件- 参数:
- 事件的字符串,要on
- 回调函数
- 这个方法也可以同时为一个事件绑定多个处理函数,不同的是它是后绑定的先执行,执行顺序和addEventListener()相反
- 参数:
<!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 type="text/css">
</style>
</head>
<body>
<button id="btn">按钮</button>
<script>
var btn = document.getElementById("btn");
btn.attachEvent("onclick", function () {
console.log(1)
})
btn.attachEvent("onclick", function () {
console.log(2)
})
btn.attachEvent("onclick", function () {
console.log(3)
})
</script>
</body>
</html>
addEventListener
和 attachEvent
的兼容写法
- 首先明确
addEventListener
和attachEvent
的区别,this的指向不同,addEventListener
的this 指向的是事件对象,attachEvent
的this指向的是window
<!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 type="text/css">
</style>
</head>
<body>
<button id="btn">按钮</button>
<script>
var btn = document.getElementById("btn");
btn.addEventListener("click", function () {
alert(this)
}, false)
</script>
</body>
</html>
<!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 type="text/css">
</style>
</head>
<body>
<button id="btn">按钮</button>
<script>
var btn = document.getElementById("btn");
btn.attachEvent("onclick", function () {
alert(this)
}, false)
</script>
</body>
</html>
- 兼容不同浏览器需要统一this的指向,通过call() 方法指定调用回调函数的对象为当前的事件对象
<!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 type="text/css">
</style>
</head>
<body>
<button id="btn">按钮</button>
<script>
var btn = document.getElementById("btn");
bind(btn, "click", function () {
alert(this);
})
function bind(obj, eventStr, callback) {
if (obj.addEventListener) {
//大部分浏览器兼容的形式
obj.addEventListener(eventStr, callback, false)
} else {
//ie8及以下
obj.attachEvent("on" + eventStr, function () {
callback.call(obj);
})
}
}
</script>
</body>
</html>
事件的传播
事件的传播的三个阶段
- 捕获阶段
- 在捕获阶段时从最外层的祖先元素,向目标元素进行事件捕获,但是默认此时不会触发事件
- 目标阶段
- 事件捕获到目标元素,捕获结束开始在目标元素上触发事件
- 冒泡阶段
- 事件从目标元素向它的祖先元素传递,一次触发祖先元素上的事件
如果希望在捕获阶段就触发事件,可以将addEventListener()的第三个参数设置为true,一般情况下我们不希望捕获阶段触发事件,所以这个参数一般都是false,这个值只控制事件执行的阶段,还是会向上冒泡
注:IE8及一下浏览器中没有捕获阶段
例:同时设置父元素和子元素的事件触发为捕获阶段,通过点击子元素时,可以看到,外层的父元素先响应了事件
<!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 type="text/css">
#test {
height: 200px;
background-color: orangered;
}
</style>
</head>
<body>
<div id="test">
<button id="btn">按钮</button>
</div>
<script>
var btn = document.getElementById("btn");
var divTest = document.getElementById("test");
btn.addEventListener("click", function () {
console.log("点击了按钮!")
}, true)
divTest.addEventListener("click", function () {
console.log("点击了div!")
}, true)
</script>
</body>
</html>