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>