1. DOM0 事件和DOM2級(jí)在事件監(jiān)聽使用方式上有什么區(qū)別?
DOM0處理程序
- DOM0可以使用內(nèi)聯(lián)方式監(jiān)聽事件
<input type="button" value="Click Here" onclick="showMessage();" />
-
在HTML中指定事件處理程序書寫很方便钩乍,但是有兩個(gè)缺點(diǎn)叶堆。
- 存在加載順序問題礼殊,如果事件處理程序在html代碼之后加載屏镊,用戶可能在事件處理程序還未加載完成時(shí)就點(diǎn)擊按鈕之類的觸發(fā)事件哥攘,存在時(shí)間差問題
- 這樣書寫html代碼和JavaScript代碼緊密耦合,維護(hù)不方便材鹦。
通過JavaScript指定事件處理程序就是把一個(gè)方法賦值給一個(gè)元素的事件處理程序?qū)傩浴?/p>
<input id="btnClick" type="button" value="Click Here" />
<script type="text/javascript">
var btnClick = document.getElementById('btnClick');
btnClick.onclick = function showMessage() {
alert(this.id);
};
</script>
- 使用DOM0級(jí)方法指定的事件處理程序被認(rèn)為是元素的方法逝淹,此時(shí)事件處理程序是在元素的作用域里中運(yùn)行,所以此時(shí)this指向的是元素本身桶唐。而且這種添加方式的缺陷是栅葡,只能存在一個(gè)處理程序,如果再次向同一個(gè)元素添加另外一個(gè)處理程序尤泽,上一個(gè)處理程序會(huì)被覆蓋欣簇。
DOM2處理程序
- DOM2級(jí)事件定義了兩個(gè)方法用于處理指定和刪除事件處理程序的操作:
- addEventListener
- removeEventListener
- 所有的DOM節(jié)點(diǎn)都包含這兩個(gè)方法,并且它們都接受三個(gè)參數(shù):
1.事件類型
2.事件處理方法
3.布爾參數(shù)坯约,如果是true表示在捕獲階段調(diào)用事件處理程序熊咽,如果是false,則是在事件冒泡階段處理闹丐。
<input id="btnClick" type="button" value="Click Here" />
<script type="text/javascript">
var btnClick = document.getElementById('btnClick');
btnClick.addEventListener('click', function() {
alert(this.id);
}, false);
</script>
- DOM2可以添加多個(gè)監(jiān)聽事件横殴,會(huì)依照點(diǎn)擊btn順序一次執(zhí)行,不會(huì)覆蓋卿拴。
2. attachEvent與addEventListener的區(qū)別衫仑?
- 在添加事件處理程序事addEventListener和attachEvent主要有幾個(gè)區(qū)別:
- 參數(shù)個(gè)數(shù)不相同梨与,這個(gè)最直觀,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í)順序無規(guī)律(添加的方法少的時(shí)候大多是按添加順序的反順序執(zhí)行的,但是添加的多了就無規(guī)律了)塘安,所以添加多個(gè)的時(shí)候糠涛,不依賴執(zhí)行順序的還好,若是依賴于函數(shù)執(zhí)行順序兼犯,最好自己處理忍捡,不要指望瀏覽器
3. 解釋IE事件冒泡和DOM2事件傳播機(jī)制?
- IE事件冒泡的流程是切黔,當(dāng)監(jiān)測(cè)到一個(gè)事件發(fā)生時(shí)砸脊,事件會(huì)從目標(biāo)元素開始向父級(jí)傳遞,直到傳遞到window(document)停止纬霞。這期間凌埂,如果遇到同樣的事件,都會(huì)激活對(duì)應(yīng)的事件處理程序诗芜。
- DOM2事件傳播機(jī)制瞳抓,當(dāng)檢測(cè)到一個(gè)事件發(fā)生時(shí),事件會(huì)從window開始伏恐,一次往子元素傳遞孩哑,成為事件捕獲,直到目標(biāo)元素脐湾,然后再?gòu)哪繕?biāo)元素傳遞到window臭笆,稱為事件冒泡。
4. 如何阻止事件冒泡? 如何阻止默認(rèn)事件愁铺?
- 阻止事件冒泡可以使用DOM時(shí)間對(duì)象的stopPropagation()方法:
<div class="ct">
<div class="box">
<button id="btn">點(diǎn)我</button>
</div>
</div>
<script>
var ct = document.querySelector('.ct');
var box = document.querySelector('.box');
var btn = document.querySelector('#btn');
document.body.addEventListener('click',function() {
console.log('body階段')
})
ct.addEventListener('click',function(e) {
e.stopPropagation()
console.log('ct階段')
})
box.addEventListener('click',function() {
console.log('box階段')
})
btn.addEventListener('click',function() {
console.log('btn階段')
})
</script>
image.png
- 可以使用preventDefault()方法阻止默認(rèn)事件:
<a id="a">點(diǎn)我</a>
<script>
var a = document.querySelector('#a');
a.addEventListener('click', function (e) {
e.preventDefault()
})
</script>
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')[0];
ct.addEventListener('click', function (e) {
if (e.target.nodeName.toLowerCase() === 'li') {
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 type="text" class="ipt-add-content" placeholder="添加內(nèi)容" />
<button id="btn-add-start">開頭添加</button>
<button id="btn-add-end">結(jié)尾添加</button>
<script>
var btnStart = document.querySelector('#btn-add-start');
var btnEnd = document.querySelector('#btn-add-end');
var ct = document.querySelectorAll('.ct')[0];
ct.addEventListener('click', function (e) {
if (e.target.nodeName.toLowerCase() === 'li') {
console.log(e.target.innerText)
}
})
btnStart.addEventListener('click', function () {
var text = document.querySelectorAll('.ipt-add-content')[0].value;
if (text === '') {
alert('不能為空')
} else {
var li = document.createElement('li');
var firstChild = ct.childNodes[0]
ct.insertBefore(li, firstChild);
li.innerText = text;
}
})
btnEnd.addEventListener('click', function () {
var text = document.querySelectorAll('.ipt-add-content')[0].value;
if (text === '') {
alert('不能為空')
} else {
var li = document.createElement('li');
li.innerText = text;
ct.appendChild(li)
}
})
</script>
7. 補(bǔ)全代碼督勺,要求:當(dāng)鼠標(biāo)放置在li元素上,會(huì)在img-preview里展示當(dāng)前l(fā)i元素的data-img對(duì)應(yīng)的圖片斤贰。
<style>
.img-preview {
width: 300px;
height: 200px;
}
img {
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<ul class="ct">
<li data-img="../image/elephant.png">鼠標(biāo)放置查看圖片1</li>
<li data-img="../image/read.jpg">鼠標(biāo)放置查看圖片2</li>
<li data-img="../image/view.jpg">鼠標(biāo)放置查看圖片3</li>
</ul>
<div class="img-preview"></div>
<script>
var ct = document.querySelectorAll('.ct')[0];
var img = document.createElement('img');
var preview = document.querySelectorAll('.img-preview')[0];
ct.addEventListener('mouseover', function (e) {
preview.appendChild(img);
var imgSrc = e.target.getAttribute('data-img');
img.setAttribute('src', imgSrc)
})
</script>