1: DOM0 事件和DOM2級(jí)在事件監(jiān)聽(tīng)使用方式上有什么區(qū)別缕题?
-
DOM0級(jí)事件處理方式:
通過(guò)javascript制定事件處理程序的傳統(tǒng)方式秀撇。就是將一個(gè)函數(shù)賦值給一個(gè)事件處理屬性揩局。至今所有瀏覽器都支持。優(yōu)點(diǎn)拍冠,簡(jiǎn)單且具有跨瀏覽器的優(yōu)勢(shì)涧团。
例:var btn = document.getElementById("btn");
btn.onclick = function(){
alert(this.id);//this指定當(dāng)前元素btn
}
刪除DOM0事件處理程序,只要將對(duì)應(yīng)事件屬性置為null即可蝙斜。
btn.onclick = null;
缺點(diǎn):一個(gè)事件處理程序只能對(duì)應(yīng)一個(gè)處理函數(shù)揍瑟。 -
DOM2級(jí)事件處理方式
DOM2級(jí)事件處理方式指定了,添加事件處理程序和刪除事件處理程序的方法乍炉。分別是:
addEventListener(eventName,func,isPuhuo);
removeEventListener(eventName,func,isPuhuo);
參數(shù)分別是,事件處理屬性名稱滤馍,處理函數(shù)岛琼,是否在捕獲時(shí)執(zhí)行事件處理函數(shù)。IE中的DOM2級(jí)事件處理使用了attachEvent和detachEvent來(lái)實(shí)現(xiàn)巢株。這倆個(gè)方法接受倆個(gè)相同的參數(shù)槐瑞,事件處理名稱和事件處理函數(shù)。IE8以及更早版本只支持冒泡型事件阁苞,所以attachEvent添加的事件都會(huì)被添加到冒泡階段困檩。
例如:
var btn = document.getElementById("btn");
btn.attachEvent("onclick",function(){
alert(this);//此處this是window
});
參考:DOM0,DOM2那槽,DOM3事件處理方式區(qū)別
2: attachEvent與addEventListener的區(qū)別悼沿?
-
a. 參數(shù)個(gè)數(shù)不相同
這個(gè)最直觀,addEventListener有三個(gè)參數(shù)骚灸,attachEvent只有兩個(gè)糟趾,attachEvent添加的事件處理程序只能發(fā)生在冒泡階段,addEventListener第三個(gè)參數(shù)可以決定添加的事件處理程序是在捕獲階段還是冒泡階段處理(我們一般為了瀏覽器兼容性都設(shè)置為冒泡階段)
-
b. 第一個(gè)參數(shù)意義不同
addEventListener第一個(gè)參數(shù)是事件類型(比如click甚牲,load)义郑,而attachEvent第一個(gè)參數(shù)指明的是事件處理函數(shù)名稱(onclick,onload)
-
c. 事件處理程序的作用域不相同
addEventListener的作用域是元素本身丈钙,this是指的觸發(fā)元素非驮,而attachEvent事件處理程序會(huì)在全局變量?jī)?nèi)運(yùn)行,this是window雏赦,所以剛才例子才會(huì)返回undefined劫笙,而不是元素id
-
d. 為一個(gè)事件添加多個(gè)事件處理程序時(shí)芙扎,執(zhí)行順序不同
addEventListener添加會(huì)按照添加順序執(zhí)行,而attachEvent添加多個(gè)事件處理程序時(shí)順序無(wú)規(guī)律(添加的方法少的時(shí)候大多是按添加順序的反順序執(zhí)行的邀摆,但是添加的多了就無(wú)規(guī)律了)纵顾,所以添加多個(gè)的時(shí)候,不依賴執(zhí)行順序的還好栋盹,若是依賴于函數(shù)執(zhí)行順序施逾,最好自己處理,不要指望瀏覽器例获。
3: 解釋IE事件冒泡和DOM2事件傳播機(jī)制汉额?
IE的事件冒泡:事件開(kāi)始時(shí)由最具體的元素接收,然后逐級(jí)向上傳播到較為不具體的元素
DOM事件流:DOM2級(jí)事件規(guī)定事件流包括三個(gè)階段榨汤,事件捕獲階段蠕搜,處于目標(biāo)階段,事件冒泡階段收壕,首先發(fā)生的是事件捕獲妓灌,為截取事件提供機(jī)會(huì),然后是實(shí)際目標(biāo)接收事件蜜宪,最后是冒泡階段
4:如何阻止事件冒泡虫埂? 如何阻止默認(rèn)事件?
事件對(duì)象根據(jù)不同類型有不同的屬性和方法圃验,但是所有事件都會(huì)包含掉伏,阻止事件冒泡(或者捕獲),以及阻止默認(rèn)事件的方法澳窑,但是在DOM和IE中具有一些不同點(diǎn)斧散。
在DOM中:
- stopPropagation()方法可以停止事件在DOM層次的傳播,即取消進(jìn)一步的事件捕獲或冒泡摊聋。
- 要阻止事件的默認(rèn)行為鸡捐,可以使用preventDefault()方法,前提是cancelable值為true麻裁,比如我們可以阻止鏈接導(dǎo)航這一默認(rèn)行為:
document.querySelector('#btn').onclick = function (e) {
e.preventDefault();
}
在IE中:
cancelBubble 默認(rèn)為false闯参,設(shè)置為true后可以取消事件冒泡
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>曉風(fēng)殘?jiān)?lt;/li>
<li>JS學(xué)習(xí)大本營(yíng)</li>
</ul>
<script>
document.querySelector('.ct').addEventListener('click', function(e){
if( e.target.tagName.toLowerCase() === 'li'){ //增加判斷鹿寨,確定點(diǎn)在了li上
console.log(e.target.innerText)
}
})
</script>
6: 補(bǔ)全代碼,要求:
- 需求1:當(dāng)點(diǎn)擊按鈕開(kāi)頭添加時(shí)在<li>這里是</li>元素前添加一個(gè)新元素薪夕,內(nèi)容為用戶輸入的非空字符串脚草;當(dāng)點(diǎn)擊結(jié)尾添加時(shí)在最后一個(gè) li 元素后添加用戶輸入的非空字符串.
- 需求2:當(dāng)點(diǎn)擊每一個(gè)元素li時(shí)控制臺(tái)展示該元素的文本內(nèi)容。
<ul class="ct">
<li>這里是</li>
<li>曉風(fēng)殘?jiān)?lt;/li>
<li>大前端</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>
//你的代碼
</script>
我的思路:1. 創(chuàng)建新元素li 2. 給li里添加非空內(nèi)容 3. 把新li添加到ul內(nèi)指定位置
首先貼出公共部分原献,同時(shí)也是需求1馏慨,和下面的代碼合在一起埂淮,完成我們的目的:
// 實(shí)現(xiàn) 當(dāng)點(diǎn)擊每一個(gè)元素li時(shí)控制臺(tái)展示該元素的文本內(nèi)容
$('.ct').addEventListener('click', function(e){
var target = e.target
if(target.tagName.toLowerCase() === 'li'){
console.log(target.innerText)
}
})
// 定義$選擇器
function $(single){
return document.querySelector(single)
}
需求2
第一種:
//分別綁定兩個(gè)按鈕
$('#btn-add-start').addEventListener('click', function(){
var newLi = document.createElement('li')
var ipt = $('.ipt-add-content')
var ct = $('.ct')
if(/\S/.test(ipt.value) && ipt.value !== ''){
newLi.innerText = ipt.value
ct.insertBefore(newLi, ct.firstChild)
}else{
alert('好歹輸入點(diǎn)什么')
}
})
$('#btn-add-end').addEventListener('click', function(){
var newLi = document.createElement('li')
var ipt = $('.ipt-add-content')
var ct = $('.ct')
if(/\S/.test(ipt.value) && ipt.value !== ''){
newLi.innerText = ipt.value
ct.appendChild(newLi)
}else{
alert('好歹輸入點(diǎn)什么')
}
})
但是這樣代碼復(fù)用性太低,所以下面使用了事件代理写隶,給兩個(gè)按鈕安排了個(gè)爸爸
第二種:
$('.btn').addEventListener('click', function(e){
var newLi = document.createElement('li')
var ipt = $('.ipt-add-content')
var ct = $('.ct')
var target = e.target
if(/\S/.test(ipt.value) && ipt.value !== ''){
newLi.innerText = ipt.value
if(target.id === 'btn-add-start'){
ct.insertBefore(newLi, ct.firstChild)
}else if(target.id === 'btn-add-end'){
ct.appendChild(newLi)
}
}
})
因?yàn)檫@里是綁定的button的爸爸倔撞,所以在整個(gè)爸爸范圍內(nèi),如果是空的慕趴,點(diǎn)擊都會(huì)出現(xiàn)彈窗,所以這里就不添加alert了痪蝇,除非把id判斷放在外層,然后里面分別再次判斷是否非空,如下面所示:
$('.btn').addEventListener('click', function(e){
var newLi = document.createElement('li')
var ipt = $('.ipt-add-content')
var ct = $('.ct')
var target = e.target
if(target.id === 'btn-add-start'){
if(/\S/.test(ipt.value) && ipt.value !== ''){
newLi.innerText = ipt.value
ct.insertBefore(newLi, ct.firstChild)
}else{alert('好歹輸入點(diǎn)什么')}
}else if(target.id === 'btn-add-end'){
if(/\S/.test(ipt.value) && ipt.value !== ''){
newLi.innerText = ipt.value
ct.appendChild(newLi)
}else{alert('好歹輸入點(diǎn)什么')}
}
})
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>
//你的代碼
</script>
思路如下:
stepA:1. ul綁定mouseover事件 2. 創(chuàng)建img子元素耙册,從li里獲取src屬性 3. 把img添加到div里
stepB:2. target綁定mouseout事件 2. 使用removeChild()方法刪除子元素img
$('.ct').addEventListener('mouseover', function(e){
var target = e.target
if(target.tagName.toLowerCase() === 'li'){
var img = document.createElement('img')
img.setAttribute('src', target.getAttribute('data-img'))
$('.img-preview').appendChild(img)
}
target.addEventListener('mouseout', function(){
$('.img-preview').removeChild(img)
})
})
function $(single){
return document.querySelector(single)
}