事件机制
事件机制分为三个阶段: 捕获阶段、目标阶段、冒泡阶段,三个阶段依次执行
addEventListener
三个参数: 事件类型、回调函数、捕获还是冒泡(默认false,冒泡) addEventListener("click",function(){},true);
事件代理(事件委托)
“事件代理”即是把原本需要绑定在子元素的响应事件(click、keydown......)委托给父元素,让父元素担当事件监听的职务。事件代理的原理是DOM元素的事件冒泡
用法:
【1】可以大量节省内存占用,减少事件注册,比如在ul上代理所有li的click事件
<ul id="list">
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
......
<li>item n</li>
</ul>
// ...... 代表中间还有未知数个 li
【2】可以实现当新增子对象时无需再次对其绑定(动态绑定事件)
假设上述的例子中列表项li就几个,我们给每个列表项都绑定了事件;
在很多时候,我们需要通过 AJAX 或者用户操作动态的增加或者删除列表项li元素,那么在每一次改变的时候都需要重新给新增的元素绑定事件,给即将删去的元素解绑事件;
如果用了事件委托就没有这种麻烦了,因为事件是绑定在父层的,和目标元素的增减是没有关系的,执行到目标元素是在真正响应执行事件函数的过程中去匹配的;所以使用事件在动态绑定事件的情况下是可以减少很多重复工作的
target currentTarget
event.target 返回触发事件的元素(在点击事件中,就相当于被你点击的那个元素对象) event.currentTarget 返回绑定事件的元素,即事件的委托对象(绑定了事件处理函数的元素)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<ul>
<li>hello 1</li>
<li>hello 2</li>
<li>hello 3</li>
<li>hello 4</li>
</ul>
<script>
let ul = document.querySelectorAll('ul')[0]
let aLi = document.querySelectorAll('li')
ul.addEventListener('click',function(e){
let oLi1 = e.target
let oLi2 = e.currentTarget
console.log(oLi1) // 被点击的li
console.log(oLi2) // ul
console.og(oLi1 === oLi2) // false
})
</script>
</body>
</html>
stopprogation和stop preventdefault
preventDefault是用来阻止浏览器的默认事件,stopPropagation是用来阻止冒泡事件(父子元素之间)
preventDefault:
<!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>
<form>
<label for="check1">Checkbox:</label>
<input type="checkbox" id="check1"/>
</form>
<a id='link1' target="_blank" href="https://www.baidu.com/">BaiDu</a>
<script>
const aDom=document.getElementById('link1')
const inputDom=document.getElementById('check1')
function bindEvent(ele,type,fn){
ele.addEventListener(type,fn)
}
bindEvent(aDom,'click',(event)=>{
event.preventDefault();
alert("我是a标签,启用阻止默认事件,不能跳转")
})
bindEvent(inputDom,'click',(event)=>{
event.preventDefault();
alert("我是多选框,启用阻止默认事件,不能点击选中")
})
</script>
</body>
</html>
stopPropagation
<!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>
<style>
.out{
width: 200px;
height: 200px;
background-color: rgb(202, 235, 20);
display: flex;
justify-content: center;
align-items: center;
}
.inner{
width: 100px;
height: 100px;
background-color: rgb(27, 200, 223);
}
</style>
<body>
<div class="content">
<div class="out">
<div class="inner"></div>
</div>
</div>
<script type="text/javascript">
//注意:冒泡事件是发生在父子元素之间
var out = document.getElementsByClassName("out")[0];
var inner = document.getElementsByClassName("inner")[0];
out.addEventListener("click", function (evt) {
alert("触发了out的点击事件");
console.log('out');
}, false);
inner.addEventListener("click", function (evt) {
alert("触发了inner的点击事件");
console.log('inner');
//在此处调用stopPropagation()会阻止冒泡事件
// evt.stopPropagation();
}, false);
</script>
</body>
</html>