一. DOM事件级别
dom事件级别包括dom0,dom2,dom3(dom1版本对dom事件没有任何修改)。这三种级别绑定事件的方法如下:
dom0绑定事件方法:
<p id = 'click'>click me</p>
<script>
document.getElementById('click').onclick = function(event){
alert(event.target);
}
</script>
解绑事件方法:
document.getElementById('click'_).onclick = null;
dom3和dom2绑定事件的方法一样,就是多了很多事件类型,比如keyup,input等事件类型,目前主流浏览器都已经支持这些事件类型,这些事件类型不仅可以用dom0方式绑定,也可以用dom2方式绑定。
dom2,dom3绑定事件方法及解绑事件方法:
var click = document.getElementById('inner');
click.addEventListener('click',function(){
alert('inner show');
},false);
let testFun = function () {
console.log("test111")
}
let dom = document.getElementById('test1')
/* addEventListener ie9以下不支持*/
dom.addEventListener('click',testFun,false)
dom.removeEventListener('click',testFun,false)
注意:这里有几个坑
1.用dom0方式绑定的事件方法,用dom2方式解绑方法是不行,总之就是何种级别绑定,就何种级别解绑。
2.addEventListener不支持ie9以下,需要考虑兼容写法,ie8以下是attachEven。
3.removeEventListener需要考虑两个方法用到的是同一个函数,否则remove无效。具体可自行搜索相关资料
4.dom0事件绑定方法,一次只能执行一个函数,多写几个,后面的会覆盖前面的,而dom2方式绑定的方法,可以依此执行。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>DOM 事件</title>
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0">
</head>
<body>
<div id="test1">111111</div>
<script type="text/javascript">
var dom = document.getElementById('test1');
dom.onclick = function () {/*方法失效,被覆盖*/
console.log("dom0-1")
}
dom.onclick = function () {/*只执行这个*/
console.log("dom0-2")
}
/* dom2绑定事件兼容ie地低版本写法 */
var Event = {};
Event.addEvents = function(target,eventType,handle,arguments){
if(document.addEventListener){
target.addEventListener(eventType,handle,arguments?arguments:false);
}else{
target.attachEvent('on'+eventType,function(){
handle.call(target,arguments);
});
}
}
Event.removeEvents = function(target,eventType,handle){
if(document.removeEventListener){
target.removeEventListener(eventType,handle,false);
}else{
target.detachEvent('on'+eventType,function(){
handle.call(target,arguments);
});
}
}
var testFun = function () {
console.log("dom2")
}
var testFun2 = function () {
console.log("dom2-2")
}
Event.addEvents(dom,"click",testFun)/*可以执行*/
Event.addEvents(dom,"click",testFun2)/*可以执行*/
dom.onclick = null //解绑dom0方法,dom2方法依然执行
Event.removeEvents(dom,"click",testFun)//解绑dom2方法
/* 实践发现document改成window,在ie9以下无效*/
document.onkeyup = function () {//能执行
console.log("onkeyup1")
}
Event.addEvents(document,"keyup",function () {//能执行
console.log("onkeyup2")
})
</script>
</body>
</html>
二. DOM事件模型
首先,IE8及以下是不支持这种事件模型的。事件捕获和事件冒泡的机制如下图:
DOM事件模型:浏览器在用户触发某个事件以后,先从window对象开始,然后从document,html,body,等等,依此层层捕获触发事件的目标元素,捕获到目标元素后,事件再依此从目标元素往上冒泡,依次是父元素,一层一层,到到body,html,ducument,window.
关键点:事件绑定,第三个参数默认false,即事件冒泡阶段处理事件函数,改为true,即在捕获阶段执行事件函数。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>DOM 事件</title>
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0">
</head>
<body>
<div id="parent">
<div id="test1">点击我</div>
</div>
<script type="text/javascript">
var dom = document.getElementById('test1');
var parent = document.getElementById('parent');
/* dom2绑定事件兼容ie地低版本写法 */
var Event = {};
Event.addEvents = function(target,eventType,handle,arguments){
if(document.addEventListener){
target.addEventListener(eventType,handle,arguments?arguments:false);
}else{
target.attachEvent('on'+eventType,function(){
handle.call(target,arguments);
});
}
}
/*事件函数在捕获阶段执行*/
Event.addEvents(document,'click',function () {
console.log('document')
},true)
Event.addEvents(document.documentElement,'click',function () {
console.log('html')
},true)
Event.addEvents(document.body,'click',function () {
console.log('body')
},true)
Event.addEvents(parent,'click',function () {
console.log('parent')
},true)
Event.addEvents(dom,'click',function (e) {
console.log('dom');
// e.stopPropagation();
},true)
/*事件函数在冒泡阶段执行*/
Event.addEvents(document,'click',function () {
console.log('document-2')
})
Event.addEvents(document.documentElement,'click',function () {
console.log('html-2')
})
Event.addEvents(document.body,'click',function () {
console.log('body-2')
})
Event.addEvents(parent,'click',function () {
console.log('parent-2')
})
Event.addEvents(dom,'click',function () {
console.log('dom-2')
})
</script>
</body>
</html>
三. DOM事件类
事件类封装了关于事件处理的很多api,常用的有:
1.preventDefault
应用例子:阻止a标签的默认跳转行为
如vue里面:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>DOM 事件</title>
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0">
</head>
<body>
<script>
function prevent(e) {
console.log(11111111);
e.preventDefault();
}
</script>
<a href="https://www.baidu.com" onclick="prevent(event)">点击我</a>
</body>
</html>
2.stopPropagation 阻止事件冒泡,太常用了,不举例了
3.stopImmediatePropagation:一个dom如果绑定多个事件函数,但是只想执行某些函数,其他函数不执行,可用该方法
<body>
<div id="parent">
<div id="test1">111111</div>
</div>
<script type="text/javascript">
var dom = document.getElementById('test1');
/* dom2绑定事件兼容ie地低版本写法 */
var Event = {};
Event.addEvents = function(target,eventType,handle,arguments){
if(document.addEventListener){
target.addEventListener(eventType,handle,arguments?arguments:false);
}else{
target.attachEvent('on'+eventType,function(){
handle.call(target,arguments);
});
}
}
Event.addEvents(dom,'click',function (event) {
console.log("dom")
event.stopImmediatePropagation()//增加这句后,其他事件函数就不执行了
})
Event.addEvents(dom,'click',function () {
console.log("dom-2")
})
</script>
</body>
4.event.target 和event.currentTarget :获取实际触发事件的dom元素,和绑定事件的dom元素,此方法即事件代理。
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
function test(e){
console.log(e.target)
console.log(e.currentTarget)
}
</script>
<ol onclick="test(event)">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
</ol>
</body>
</html>