題目1: DOM0 事件和DOM2級(jí)在事件監(jiān)聽使用方式上有什么區(qū)別贸营?
事件處理程序
我們也稱之為事件偵聽器(listener)岩睁,事件就是用戶或?yàn)g覽器自身執(zhí)行的某種動(dòng)作。比如click冰啃、load、mouseover等焚刚,都是事件類型(俗稱事件名稱)扇调,而響應(yīng)某個(gè)事件的方法就叫做事件處理程序或者事件監(jiān)聽器
-
DOM0級(jí)事件處理程序
在DOM0級(jí)事件處理程序狼钮,事件名以'on'開頭,因此click事件的事件處理程序就是onclick莲镣、load事件的事件處理程序就是onload涎拉。
HTML事件處理程序
一個(gè)HTML元素支持事件,可以通過HTML元素的屬性來指定:
<input type="button" value="這是個(gè)按鈕" onclick="showMessage()" >
上面的input對(duì)應(yīng)的onclick事件處理程序如下:
上面通過HTML元素屬性添加事件處理程序的方式半火,屬于DOM0事件處理程序慈缔。通過上面的方式添加會(huì)有一定的麻煩种玛,HTML與JavaScript代碼緊密耦合,對(duì)代碼修改和維護(hù)都造成了不便娱节。function showMessage(){ alert('itbilu.com'); }
通過JavaScript添加DOM0事件處理程序
要使用JavaScript指定事件處理程序祭示,首先要獲得一個(gè)要操作的對(duì)象的引用质涛,然后通過其事件處理程序?qū)傩裕ㄟ@些屬性通常全部小寫,例如:onclick)怒炸,指定事件處理程序毡代。
DOM0級(jí)事件處理程序可以認(rèn)為是元素的方法。刪除DOM0級(jí)事件處理程序捏鱼,將相應(yīng)屬性值設(shè)置為null即可导梆。var btn = document.getElementById("myBtn"); btn.onclick = function(){ alert('itbilu.com'); }
btn.onclick = null;
-
DOM2級(jí)事件處理程序
在W3C制定的DOM2規(guī)范中,其中的DOM 事件規(guī)范定義了兩個(gè)方法:addEventListener()和removeEventListener()猿诸,分別用于添加事件處理程序和刪除事件處理程序狡忙。
所有的DOM節(jié)點(diǎn)都包含這兩個(gè)方法址芯,并且它們都接受三個(gè)參數(shù):事件類型谷炸、事件處理方法、布爾參數(shù)(如果是true表示在捕獲階段調(diào)用事件處理程序拓颓,如果是false描孟,則是在事件冒泡階段處理)匿醒。var btn = document.getElementById("myBtn"); btn.addEventListener("click", showMessage, false);
使用DOM2級(jí)方法添加事件處理程序時(shí),可以為指定元素添加多個(gè)事件處理程序溉痢。
刪除DOM2級(jí)事件處理程序方法如下:var btn = document.getElementById("myBtn"); btn.addEventListener("click", showMessage, false); btn.addEventListener("click", showMessage2, false);
btn.removeEventListener("click", showMessage, false);
attachEvent()與detachEvent()
在早期的IE瀏覽器憋他,如:IE8中竹挡,沒有實(shí)現(xiàn)addEventListener()和removeEventListener(),但提供了兩個(gè)替代方法attachEvent()和detachEvent()汽畴。由于Microsoft當(dāng)前最新的系統(tǒng)Windows 10中,已放棄IE被edge瀏覽器替代鲁猩,所在attachEvent()和detachEvent()已沒有意義罢坝。
題目2: attachEvent與addEventListener的區(qū)別嘁酿?
-
參數(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辆飘,所以剛才例子才會(huì)返回undefined谓传,而不是元素id
-
為一個(gè)事件添加多個(gè)事件處理程序時(shí),執(zhí)行順序不同
addEventListener添加會(huì)按照添加順序執(zhí)行紧卒,而attachEvent添加多個(gè)事件處理程序時(shí)順序無規(guī)律(添加的方法少的時(shí)候大多是按添加順序的反順序執(zhí)行的跑芳,但是添加的多了就無規(guī)律了),所以添加多個(gè)的時(shí)候怀樟,不依賴執(zhí)行順序的還好盆佣,若是依賴于函數(shù)執(zhí)行順序共耍,最好自己處理,不要指望瀏覽器
題目3: 解釋IE事件冒泡和DOM2事件傳播機(jī)制穆咐?
-
IE事件冒泡
如下圖佃蚜,對(duì)一個(gè)例如div這樣的子容器進(jìn)行事件監(jiān)聽谐算,IE的傳播機(jī)制是從事件目標(biāo)節(jié)點(diǎn)逐步的向上層結(jié)點(diǎn)傳播归露,直到到達(dá)根結(jié)點(diǎn)
-
DOM2事件流
如下圖剧包,對(duì)一個(gè)例如這樣的子容器進(jìn)行事件監(jiān)聽,DOM2的傳播機(jī)制是先從頂層根結(jié)點(diǎn)開始一級(jí)一級(jí)向下傳播一铅,直到傳到目標(biāo)節(jié)點(diǎn)堕油,這一階段叫做事件捕獲掉缺;最后事件從目標(biāo)節(jié)點(diǎn)一級(jí)一級(jí)向頂層根結(jié)點(diǎn)傳播,這一階段叫做事件冒泡艰毒。DOM2事件流是事件冒泡和事件捕獲的結(jié)合搜囱。
題目4:如何阻止事件冒泡? 如何阻止默認(rèn)事件冰单?
阻止事件冒泡可以使用DOM中的事件對(duì)象的方法:stopPropagation()
stopPropagation()方法可以停止事件在DOM層次的傳播诫欠,即取消進(jìn)一步的事件捕獲或冒泡浴栽。我們可以在button的事件處理程序中調(diào)用stopPropagation()從而避免注冊(cè)在body上的事件發(fā)生
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);
阻止默認(rèn)事件可以使用DOM中事件對(duì)象的方法:preventDefault()
典鸡,前提是cancelable值為true,比如我們可以阻止鏈接導(dǎo)航這一默認(rèn)行為
document.querySelector('#btn').onclick = function (e) { e.preventDefault(); }
對(duì)于IE瀏覽器嫁乘,阻止事件冒泡可以使用event對(duì)象的方法:cancelBubble()
球碉,默認(rèn)為false睁冬,設(shè)置為true后可以取消事件冒泡;在IE瀏覽器下阻止默認(rèn)事件可以使用:returnValue()
直奋,默認(rèn)為true脚线,設(shè)為false可以取消事件默認(rèn)行為弥搞。
題目5:有如下代碼,要求當(dāng)點(diǎn)擊每一個(gè)元素li時(shí)控制臺(tái)展示該元素的文本內(nèi)容斯碌。不考慮兼容
<ul class="ct">
<li>這里是</li>
<li>饑人谷</li>
<li>前端6班</li>
</ul>
<script>
//todo ...
var ct = document.querySelector('.ct');
ct.addEventListener('click', function(e){
console.log(e.target.innerText);
});
</script>
題目6: 補(bǔ)全代碼傻唾,要求:
當(dāng)點(diǎn)擊按鈕開頭添加時(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">開頭添加</button>
<button id="btn-add-end">結(jié)尾添加</button>
<script>
//你的代碼
var ct = document.querySelector('.ct'),
addStartBtn = document.querySelector('#btn-add-start'),
addEndBtn = document.querySelector('#btn-add-end'),
ipt = document.querySelector('.ipt-add-content');
ct.addEventListener('click', function(e){
if(e.target.tagName.toLowerCase() === 'li'){
console.log(e.target.innerText);
}
});
addStartBtn.addEventListener('click', function(){
if(ipt.value){
var li = document.createElement('li');
li.innerText = ipt.value;
ct.insertBefore(li,ct.firstChild);
}
});
addEndBtn.addEventListener('click', function(){
if(ipt.value){
var li = document.createElement('li');
li.innerText = ipt.value;
ct.appendChild(li);
}
})
</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'),
preview = document.querySelector('.img-preview')
ct.addEventListener('mouseover', function(e){
if(e.target.tagName.toLowerCase() === 'li'){
var image = document.createElement('img');
image.src = e.target.dataset.img;
preview.appendChild(image);
}
})
ct.addEventListener('mouseout', function(e){
if(e.target.tagName.toLowerCase() === 'li'){
preview.innerHTML = '';
}
})
</script>