1.事件代理
- 事件代理:为子元素添加监听器转变为为父容器添加监听器,然后通过event.target判断具体操作的元素
- 事件的传递是和文档结构有关的
1.DOM0级和DOM2级在事件监听使用方式上有什么区别?
-
DOM0级事件处理程序
- 使用DOM0级方法指定的事件处理程序被认为是元素的方法,因此,事件处理程序是在元素的作用域中运行
var btn = document.getElementById('btn'); btn.onclick = function (){ console.log(this.id); // btn }
- 使用DOM0级方法只能为元素的一个事件指定一个处理程序,后面指定的会覆盖前面指定的(因为事件处理程序被认为是元素的方法,同一事件则方法名相同)
// 后一个事件处理程序会覆盖前一个事件处理程序 var btn = document.getElementById('btn'); btn.onclick = function (){ console.log(this.id); } btn.onclick = function (){ console.log("hello"); }
- 使用DOM0级方法删除事件处理程序
var btn = document.getElementById('btn'); btn.onclick = function (){ console.log(this.id); } btn.onclick = null;
- 使用DOM0级方法指定的事件处理程序兼容IE较低版本
-
DOM2级事件处理程序
- 使用DOM2级方法指定的事件处理程序
var btn = document.getElementById('btn'); btn.addEventListener("click", function(){ console.log("test"); });
function handler(){ console.log("test"); } var btn = document.getElementById('btn'); btn.addEventListener("click", handler);
- 使用DOM2级方法可以为元素针对多个事件指定多个处理程序,这些事件处理程序会按照添加顺序依次执行
var btn = document.getElementById('btn'); function handler(){ console.log("test"); } btn.addEventListener("click", function(){ console.log("test"); }); btn.addEventListener("click", handler);
- 使用DOM2级方法可以为元素删除事件处理程序,但是指定的匿名事件处理函数无法删除
btn.removeEventListener("click", handler);
- 使用DOM2级事件处理程序可以指定在哪一阶段调用事件处理程序(捕获阶段or冒泡阶段)
btn.addEventListener("click", handler, false); // 在冒泡阶段调用事件处理程序 btn.addEventListener("click", handler, true); // 在捕获阶段调用事件处理程序
- 使用addEventListener为元素添加的事件处理程序也是在其依附的元素的作用域中运行
var btn = document.getElementById('btn'); function handler(){ console.log(this.id); } btn.addEventListener("click", handler); // 触发时输出 btn
2.attachEvent与addEventListener的区别?
- 在低版本IE浏览器中,只支持事件冒泡,因此不支持addEventListener和removeEventListener方法,但是实现了类似的两个方法:attachEvent和detachEvent
- addEventListener:
- 可以指定2或3个参数
- 可以指定在哪一阶段调用事件处理程序(捕获阶段or冒泡阶段),默认是冒泡阶段
- addEventListener第一个参数是事件类型(比如click,load)
- 为元素添加的事件处理程序是在其依附的元素的作用域中运行
- addEventListener针对一个事件添加的多个事件处理程序会按照添加顺序执行
- attachEvent:
- 只能指定2个参数
- 添加的事件处理程序都会在冒泡阶段被执行,无法指定在哪一阶段调用事件处理程序
- attachEvent第一个参数是事件处理函数名称(比如onclick,onload)
- 为元素添加的事件处理程序是在全局作用域中运行
- 事件处理函数名称针对一个事件添加的多个事件处理程序会无规律执行
3.解释IE事件冒泡和DOM2事件传播机制?
- IE的事件冒泡:事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的元素
- Netscape的事件捕获:不太具体的节点更早接收事件,而最具体的元素最后接收事件,和事件冒泡相反
- DOM事件流:DOM2级事件规定事件流包括三个阶段,事件捕获阶段,处于目标阶段,事件冒泡阶段,首先发生的是事件捕获,为截取事件提供机会,然后是实际目标接收事件,最后是冒泡阶段
4.如何阻止事件冒泡? 如何阻止默认事件?
- 阻止事件冒泡:event.stopPropagation();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<h1>hello!</h1>
</div>
<script>
var html = document.documentElement;
var body = document.body;
var div = document.querySelector("div");
var h1 = document.querySelector("h1");
window.addEventListener("click",function(){
console.log(1);
},true);
window.addEventListener("click",function(){
console.log(1);
});
document.addEventListener("click",function(){
console.log(2);
},true);
document.addEventListener("click",function(){
console.log(2);
});
html.addEventListener("click",function(){
console.log(3);
},true);
html.addEventListener("click",function(){
console.log(3);
});
body.addEventListener("click",function(){
console.log(4);
},true);
body.addEventListener("click",function(){
console.log(4);
});
div.addEventListener("click",function(){
console.log(5);
//如果没有阻止捕获/冒泡,点击hello! 会输出1 2 3 4 5 6 6 5 4 3 2 1
//如果阻止捕获/冒泡,点击hello! 会输出1 2 3 4 5
event.stopPropagation();
},true);
div.addEventListener("click",function(){
console.log(5);
});
h1.addEventListener("click",function(){
console.log(6);
},true);
h1.addEventListener("click",function(){
console.log(6);
});
</script>
</body>
</html>
- 阻止默认事件:event.preventDefault();
//阻止点击a标签后导致的页面跳转
<a href="www.baidu.com" id="link">baidu</a>
<script>
function prevent(event){
event.preventDefault();
}
var link = document.getElementById("link");
link.addEventListener("click", prevent);
</script>
5.有如下代码,要求当点击每一个元素li时控制台展示该元素的文本内容。
- 事件委托/事件代理:对于"事件处理程序过多"问题的解决方案就是事件委托/事件代理.事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件.使用事件委托结束解决以下问题,只需要在DOM树中尽量高的层次上添加一个事件处理程序.
<ul class="ct">
<li>aaaa</li>
<li>bbbb</li>
<li>cccc</li>
</ul>
<script>
function outputInnerText(event){
var target = event.target;
console.log(target.innerHTML);
}
var ul = document.querySelector(".ct");
ul.addEventListener("click", outputInnerText);
</script>
6.补全代码,要求:
- 当点击按钮开头添加时在<li>这里是</li>元素前添加一个新元素,内容为用户输入的非空字符串;当点击结尾添加时在最后一个 li 元素后添加用户输入的非空字符串.
- 当点击每一个元素li时控制台展示该元素的文本内容。
<div>
<ul class="ct">
<li>aaaa</li>
<li>bbbb</li>
<li>cccc</li>
</ul>
<input class="ipt-add-content" placeholder="添加内容"/>
<button id="btn-add-start">开头添加</button>
<button id="btn-add-end">结尾添加</button>
</div>
<script>
var ul = document.querySelector(".ct");
var btn_add_start = document.querySelector("#btn-add-start");
var btn_add_end = document.querySelector("#btn-add-end");
var content = document.querySelector(".ipt-add-content");
btn_add_start.onclick = function (event) {
if(content.value.length < 1 ){
alert('请输入项目名称');
}else{
var newNode = document.createElement("li");
newNode.innerHTML = content.value;
ul.insertBefore(newNode, ul.firstElementChild);
content.value = "";
}
}
btn_add_end.onclick = function (event) {
if(content.value.length < 1 ){
alert('请输入项目名称');
}else{
var newNode = document.createElement("li");
newNode.innerHTML = content.value;
ul.appendChild(newNode);
content.value = "";
}
}
function outputInnerText(event){
var target = event.target;
console.log(target.innerHTML);
}
ul.addEventListener("click", outputInnerText);
</script>
7.补全代码,要求:当鼠标放置在li元素上,会在img-preview里展示当前li元素的data-img对应的图片。
<ul class="ct">
<li data-img="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1487859573373&di=7467cab77ceaa0739cb8a0acd5857623&imgtype=0&src=http%3A%2F%2Fwww.kele8.com%2Fuploadfile%2F2014%2F0326%2F20140326034001805.jpg">鼠标放置查看图片1</li>
<li data-img="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1487859916531&di=cbdd990e7d9dcbcb409168363182137a&imgtype=0&src=http%3A%2F%2Fh7.86.cc%2Fwalls%2F20150906%2F1024x768_43422cf79b8229f.jpg">鼠标放置查看图片2</li>
<li data-img="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1487859633187&di=b78c30783aaa1c04ef82ae6f398900fd&imgtype=0&src=http%3A%2F%2Fimg1.gamedog.cn%2F2014%2F04%2F22%2F43-1404221025080.jpg">鼠标放置查看图片3</li>
</ul>
<div class="img-preview"></div>
<script>
//使用事件代理/事件委托
var ul = document.querySelector(".ct");
var imgPreview = document.querySelector(".img-preview");
function agentMouseOver(event){
var target = event.target;
var imageName = target.getAttribute("data-img");
var image = document.createElement('img');
image.setAttribute("src", imageName);
if(imgPreview.firstElementChild != null){
imgPreview.replaceChild(image,imgPreview.firstElementChild );
}else{
imgPreview.appendChild(image);
imgPreview.firstElementChild.addEventListener("click", prevent);
}
}
ul.addEventListener("mouseover", agentMouseOver);
function closeImage(event){
if(imgPreview.firstElementChild != null){
imgPreview.removeEventListener("click", prevent);
imgPreview.removeChild(imgPreview.firstElementChild);
}
}
function prevent(event){
event.stopPropagation();
}
document.addEventListener("click", closeImage);
imgPreview.addEventListener("click", prevent);
</script>