1.DOM0 事件和DOM2級(jí)在事件監(jiān)聽(tīng)使用方式上有什么區(qū)別?
DOM0事件是將一個(gè)函數(shù)賦值給一個(gè)事件處理程序?qū)傩裕?/p>
var btn=document.getElementById("myBtn");
btn.omclick=function(){
alert(this.id);//"myBtn"
};
使用DOM0級(jí)方法指定的事件處理程序被認(rèn)為是元素的方法。此時(shí)事件處理程序是在元素的作用域中運(yùn)行,程序中的this引用當(dāng)前元素。DOM0的優(yōu)勢(shì)在于基本上所有的瀏覽器都支持,劣勢(shì)在于因?yàn)槭墙o元素的屬性賦值的方式來(lái)添事件處理程序,所以再次向同一個(gè)元素添加另一個(gè)事件處理程序,上一個(gè)處理程序會(huì)被覆蓋。
DOM2事件定義了兩個(gè)方法,addEventListener()和removeEventListener(),用于處理指定和刪除事件處理程序的操作,所有DOM節(jié)點(diǎn)都包含這兩個(gè)方法,并且它們都接受三個(gè)參數(shù):處理事件名、處理事件程序的函數(shù)、布爾值;布爾值是true表示在捕獲階段調(diào)用事件處理程序,如果是false,表示在冒泡階段調(diào)用事件處理程序:
var btn = document.getElementById("myBtn");
btn.addEventListener("click",function(){
alert(this.id);
},flase);
與DOM0方法一樣,這里的處理程序也是在其依附的元素作用域中運(yùn)行。DOM2方法的好處是可以添加多個(gè)事件處理程序
2.attachEvent與addEventListener的區(qū)別?
-
適應(yīng)的瀏覽器版本不同
attachEvent方法適用于IEaddEventListener方法適用于Mozilla/Webkit -
參數(shù)個(gè)數(shù)不相同
addEventListener有三個(gè)參數(shù),attachEvent只有兩個(gè),attachEvent添加的事件處理程序只能發(fā)生在冒泡階段,addEventListener第三個(gè)參數(shù)可以決定添加的事件處理程序是在捕獲階段還是冒泡階段處理(我們一般為了瀏覽器兼容性都設(shè)置為冒泡階段) -
第一個(gè)參數(shù)意義不同
addEventListener第一個(gè)參數(shù)是事件類型(比如click,load),而attachEvent第一個(gè)參數(shù)指明的是事件處理函數(shù)名稱(onclick,onload) -
事件處理程序的作用域不相同
addEventListener的作用域是元素本身,this是指的觸發(fā)元素,而attachEvent事件處理程序會(huì)在全局變量?jī)?nèi)運(yùn)行,this是window -
為一個(gè)事件添加多個(gè)事件處理程序時(shí),執(zhí)行順序不同
addEventListener添加會(huì)按照添加順序執(zhí)行,而attachEvent添加多個(gè)事件處理程序時(shí)順序無(wú)規(guī)律
3. 解釋IE事件冒泡和DOM2事件傳播機(jī)制?
IE事件冒泡
事件最開(kāi)始時(shí)由最具體的元素(文檔中嵌套層次最深的那個(gè)節(jié)點(diǎn))接收,然后逐級(jí)向上傳播到較為不具體的節(jié)點(diǎn)(文檔)。以下面的HTML頁(yè)面為例:
<!DOCTYPE html>
<html>
<head>
<title>exp</title>
</head>
<body>
<div id="my">Click me</div>
</body>
</html>
如果你點(diǎn)擊了頁(yè)面中的<div>元素,那么這個(gè)click事件會(huì)按照如下順序傳播:
(1)<div>
(2)<body>
(3)<html>
(4)document
也就是說(shuō),click事件首先在<div>元素上發(fā)生,而這個(gè)元素就是我們點(diǎn)擊的元素。然后,click事件沿著DOM樹(shù)向上傳播,在每一級(jí)節(jié)點(diǎn)上都會(huì)發(fā)生,直至傳播到document對(duì)象。過(guò)程如下圖:

DOM2事件傳播機(jī)制
"DOM2級(jí)事件"規(guī)定的時(shí)間溜包括三個(gè)階段:事件捕獲階段,處于目標(biāo)階段和事件冒泡階段。首先發(fā)生的是事件捕獲,為截獲事件提供了機(jī)會(huì)。然后是實(shí)際的目標(biāo)接收到事件。最后一個(gè)階段是冒泡階段,可以在這個(gè)階段對(duì)事件做出響應(yīng)。以前面簡(jiǎn)單的HTML頁(yè)面為例。單擊<div>元素會(huì)按照下圖所示順序觸發(fā)事件。

4.如何阻止事件冒泡? 如何阻止默認(rèn)事件?
阻止默認(rèn)事件
阻止事件的默認(rèn)行為,可以使用preventDefault()方法,前提是cancelable值為true,比如我們可以阻止鏈接導(dǎo)航這一默認(rèn)行為
document.getElementsByTagName('a').onclick = function (e) {
e.preventDefault();
}
阻止事件冒泡
stopPropagation()方法可以停止事件在DOM層次的傳播,即取消進(jìn)一步的事件捕獲或冒泡
var handler = function (e) {
alert(e.type);
e.stopPropagation();
}
addEvent(document.body, 'click', function () { alert('Clicked body')});
var btnClick = document.getElementById('btnClick');
addEvent(btnClick, 'click', handler);
上述代碼的body 的alert('Clicked body')不會(huì)i執(zhí)行,因?yàn)閮?nèi)部的事件冒泡被阻止了。
5.有如下代碼,要求當(dāng)點(diǎn)擊每一個(gè)元素li時(shí)控制臺(tái)展示該元素的文本內(nèi)容。不考慮兼容
<ul class="ct">
<li>這里是</li>
<li>饑人谷</li>
<li>前端6班</li>
</ul>
<script>
var ct= document.getElementsByClassName('ct');
console.log(ct);
ct[0].addEventListener("click",function(e){
var target= e.target;
if(target.tagName.toLowerCase() === "li"){
console.log(target.innerText);
}
})
</script>
6. 補(bǔ)全代碼,要求:
- 當(dāng)點(diǎn)擊按鈕開(kāi)頭添加時(shí)在
<li>這里是</li>元素前添加一個(gè)新元素,內(nèi)容為用戶輸入的非空字符串;當(dāng)點(diǎn)擊結(jié)尾添加時(shí)在最后一個(gè) li 元素后添加用戶輸入的非空字符串. - 當(dāng)點(diǎn)擊每一個(gè)元素li時(shí)控制臺(tái)展示該元素的文本內(nèi)容。
<ul class="ct">
<li>這里是</li>
<li>饑人谷</li>
<li>任務(wù)班</li>
</ul>
<input class="ipt-add-content" placeholder="添加內(nèi)容" />
<button id="btn-add-start">開(kāi)頭添加</button>
<button id="btn-add-end">結(jié)尾添加</button>
<script>
var ct = document.getElementsByClassName('ct');
var ipt = document.getElementsByClassName('ipt-add-content');
var star_btn = document.getElementById('btn-add-start');
var end_btn = document.getElementById('btn-add-end');
console.log(ipt);
ct[0].addEventListener("click", function(e) {
var target = e.target;
if (target.tagName.toLowerCase() === "li") {
console.log(target.innerText);
}
});
end_btn.addEventListener("click", function() {
if ((/\S/.test(ipt[0].value))) {
var node = document.createElement('li');
node.innerText = ipt[0].value;
ct[0].appendChild(node);
}
});
star_btn.addEventListener("click", function() {
if ((/\S/.test(ipt[0].value))) {
var node = document.createElement('li');
node.innerText = ipt[0].value;
ct[0].insertBefore(node, ct[0].firstChild);
}
});
</script>
7.補(bǔ)全代碼,要求:當(dāng)鼠標(biāo)放置在li元素上,會(huì)在img-preview里展示當(dāng)前l(fā)i元素的data-img對(duì)應(yīng)的圖片。
<ul class="ct">
<li data-img="1.png">鼠標(biāo)放置查看圖片1</li>
<li data-img="2.png">鼠標(biāo)放置查看圖片2</li>
<li data-img="3.png">鼠標(biāo)放置查看圖片3</li>
</ul>
<div class="img-preview"></div>
<script>
var ct = document.querySelector('.ct');
var preview = document.querySelector('.img-preview');
var img_node = document.createElement('img');
preview.appendChild(img_node);
ct.addEventListener('mouseover',function(e){
var target = e.target;
if(target.tagName.toLowerCase()==="li"){
var img_data = target.getAttribute('data-img');
img_node.setAttribute('src',img_data);
}
});
ct.addEventListener('mouseout',function(e){
img_node.setAttribute('src','');
});
</script>