-
DOM0 事件和DOM2級(jí)在事件監(jiān)聽使用方式上區(qū)別
dom0事件無法給一個(gè)事件添加多個(gè)事件處理程序拟杉,后面的程序會(huì)覆蓋后面的程序
dom2事件定義了addEventListener()和removeEventListener()用于指定和刪除事件處理程序搬设。所有的dom節(jié)點(diǎn)都包含這兩種方法撕捍,并且他們接受3個(gè)參數(shù)忧风。要處理的事件名、作為事件處理程序的函數(shù)和布爾值腿宰。最后,如果這個(gè)布爾值參數(shù)是true甩挫,表示在捕獲階段調(diào)用事件處理程序捶闸;如果是false表示在冒泡階段調(diào)用事件處理程序删壮。
但是,通過removeEventListener()函數(shù)來移除事件處理程序時(shí)央碟,移除時(shí) 的參數(shù)必須與添加處理程序時(shí)用的參數(shù)相同亿虽,這也意味著通過addEventListener添加的匿名函數(shù)將無法移除洛勉。
-
addEventListener和attachEvent區(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ā)的元素,addachEvent事件處理程序會(huì)在全局變量中運(yùn)行洽糟,this指的是window.
- 為一個(gè)事件添加多個(gè)事件處理程序時(shí)坤溃,執(zhí)行順序不同。addEventListener添加會(huì)按照添加的順序執(zhí)行祠饺,而attachEvent添加多個(gè)事件處理程序時(shí)順序無規(guī)律汁政。
-
解釋IE事件冒泡和DOM2事件傳播機(jī)制
事件冒泡
事件處理器事件處理器就是當(dāng)瀏覽器或者h(yuǎn)tml某個(gè)元素觸發(fā)某個(gè)事件時(shí)所執(zhí)行的函數(shù)记劈,事件處理器也叫事件監(jiān)聽器目木。常見的事件有l(wèi)oad/click/mouseover/mouseout刽射。
HTML元素是逐層嵌套的,對(duì)于這樣的一個(gè)結(jié)構(gòu)懈息,如果父級(jí)元素和子級(jí)元素同時(shí)都有事件監(jiān)聽器辫继,瀏覽器會(huì)如何處理呢戒祠?比如點(diǎn)擊父級(jí)元素的時(shí)候alert('parentEvent')。當(dāng)用戶點(diǎn)擊子元素對(duì)的時(shí)候,因?yàn)樽釉厍短自诟讣?jí)元素中馏颂,所以點(diǎn)擊子元素也一定會(huì)觸發(fā)父級(jí)元素的事件處理器救拉,但是這牽扯到一個(gè)出發(fā)順序的問題亿絮,到底是先彈出子元素的內(nèi)容呢還是先彈出父元素的內(nèi)容呢?這就是事件流討論的內(nèi)容黔姜。
在開發(fā)第四代瀏覽器的時(shí)候秆吵,ie4和netscape4給出了兩個(gè)完全相反的思考方式。ie支持事件冒泡纳寂,而netscape支持事件捕獲毙芜,那么什么是事件冒泡争拐?什么又是事件捕獲呢?
事件冒泡子元素嵌套在父元素內(nèi)部灯抛,點(diǎn)擊子元素的時(shí)候一定同時(shí)點(diǎn)擊了父元素对嚼,這個(gè)時(shí)候绳慎,先觸發(fā)子元素的事件處理器杏愤,然后再觸發(fā)父元素的事件處理器珊楼,如果父元素的父元素還有處理器,就一直向上觸發(fā)画舌,一直到body元素曲聂。就像魚吐泡泡一樣佑惠,從水下向水面走,每向上走一層就會(huì)查看這一層有沒有事件處理器贞奋,如果有的話就會(huì)觸發(fā)忆矛,如果沒有的話请垛,就繼續(xù)向上尋找宗收,直到頂層的body混稽,才結(jié)束尋找事件匈勋。
事件捕獲則和事件冒泡正好相反,點(diǎn)擊的時(shí)候從body往下找痘系,如果父級(jí)元素有事件處理器就先觸發(fā)父級(jí)元素的事件處理器汰翠,再向下一層复唤,如果子級(jí)元素有的話就觸發(fā)子級(jí)元素的事件處理器烛卧,直到這個(gè)點(diǎn)擊位置的最底層唱星,也就是我們通常說的target间聊。事件捕獲就好像一塊石頭從水面向水下沉一樣哎榴,如果這一層有事件處理器尚蝌,就觸發(fā),沒有就繼續(xù)向下沉衣形,到下層再查看是否有事件處理器谆吴,有的話就觸發(fā)苛预,沒有的話就繼續(xù)向下腻菇,一直到最低層筹吐,這個(gè)石頭就停止了丘薛。
在ie4瀏覽器中會(huì)先觸發(fā)子元素的事件榔袋,然后再觸發(fā)父元素的事件凰兑。但是在netscape4瀏覽器中則相反吏够。
DOM2事件的傳播機(jī)制
這樣的兩種事件流處理方式,也導(dǎo)致了瀏覽器兼容性的問題滩报,為了解決這個(gè)問題锅知,dom2級(jí)規(guī)范統(tǒng)一了事件流的過程,總共分為三個(gè)階段:事件捕獲脓钾、在目標(biāo)元素上售睹、事件冒泡。dom2級(jí)規(guī)范將事件冒泡和事件捕獲都收入自己的囊中可训,所以你可以在一個(gè)元素上同時(shí)注冊(cè)事件冒泡和事件捕獲昌妹,也就是你可以選擇父級(jí)元素事件處理器后觸發(fā)捶枢,也可以先觸發(fā),甚至可以選擇先觸發(fā)飞崖,甚至可以選擇先觸發(fā)父級(jí)元素的捕獲事件烂叔,載觸發(fā)父級(jí)元素的冒泡事件。聽上去很復(fù)雜蒜鸡,那么dom2是如何實(shí)現(xiàn)這個(gè)效果的呢胞四?
定義了addEventListener()和removeEventListener()。有些人會(huì)說,我的事件處理器不是通過dom2級(jí)規(guī)范添加的,是通過dom0級(jí)規(guī)范添加的例如:
var outer=document.getElementById('outer'),
inner=document.getElementById('inner');
var outHandler=function(){
alert('outer')
}
var innerHandler=function(){
alert('inner')
}
outer.onclick=outerHandler;
inner.onclick=innerHandler;
那這種情況是先彈出outer還是先彈出inner呢?根據(jù)dom0規(guī)范,這種添加事件處理器的方法會(huì)在冒泡階段r事件處理器。所以你想控制事件處理器是在冒泡階段還是在捕獲階段觸發(fā)莫湘,只能通過dom2級(jí)規(guī)范的方式來添加事件處理器军洼,如果你很確定自己的事件處理器是在冒泡階段才能觸發(fā),那么你也可以使用dom0級(jí)規(guī)范的方式。
-
如何阻止事件冒泡? 如何阻止默認(rèn)事件?
阻止事件冒泡
document.querySelector('.box').addEventListener('click',function(e){
e.stopPropagation()
console.log('haha')
})
阻止默認(rèn)事件
document.querySelector('box').addEventListener('click',function(e){
e.preventDefault()
console.log('hello')
})
-
要求當(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.querySelector('.ct')
ct.addEventListener('click',function(e){
console.log(e.target.innerText)
})
</script>
- 當(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 btn1=document.querySelector('#btn-add-start')
var btn2=document.querySelector('#btn-add-end')
var ct=document.querySelector('.ct')
var ipt=document.querySelector('.ipt-add-content')
btn1.addEventListener('click',function(){
var Li=document.createElement('li')
if(ipt.value){
Li.innerText=ipt.value
ct.insertBefore(Li,ct.firstChild)
}
})
btn2.addEventListener('click',function(){
var Li=document.createElement('li')
if(ipt.value){
Li.innerText=ipt.value
ct.appendChild(Li)
}
})
ct.addEventListener('click',function(e){
console.log(e.target.innerText)
})
</script>
- 補(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 img=document.querySelector('.img-preview')
ct.addEventListener('mouseover',function(e){
var imagelink=e.target.getAttribute('data-img');
var image=document.createElement('img');
image.setAttribute('src','imagelink');
img.appendChild(image);
});
</script>