一、DOM0 事件和 DOM2 級(jí)在事件監(jiān)聽(tīng)使用方式上有什么區(qū)別漫拭?
1. DOM0 級(jí)事件處理
DOM0 級(jí)事件處理,事件名以on
開(kāi)頭下翎,如onclick
缤言、onload
等。
- 在 HTML 上進(jìn)行事件處理
<button onclick="clickFnc()">點(diǎn)擊</button>
<script>
function clickFnc(){
alert('Hi');
}
</script>
通過(guò)這種方式添加事件视事,會(huì)使 HTML 和 JS 耦合在一起胆萧,不容易維護(hù)和 bug 排查。
- 通過(guò) JS 添加事件
<button id="btn">點(diǎn)擊</button>
<script>
var btn = document.getElementById('btn');
btn.onclick = function (){
alert('Hi');
};
</script>
要添加一個(gè)事件俐东,就需要先獲得對(duì)應(yīng)的 DOM 元素跌穗,然后把事件綁定在元素上面。DOM0 級(jí)在同一個(gè)元素上綁定同一個(gè)事件會(huì)覆蓋虏辫,而清除事件只需要
btn.onclick = null
即可蚌吸。
2. DOM2 級(jí)事件處理
W3C標(biāo)準(zhǔn)為 DOM2 級(jí)事件規(guī)范添加了兩個(gè)方法
addEventListener()
removeEvenListener()
,分別用于添加事件和移除事件砌庄。
<button id="btn">點(diǎn)擊</button>
<script>
var btn = document.getElementById('btn');
btn.addEvenListener('click', clickFnc, false);
function clickFnc(){
alert('Hi');
}
</script>
移除事件
btn.removeEventListener("click", clickFnc, false);
參考: JavaScript DOM文檔事件-DOM0羹唠、DOM2級(jí)事件處理程序
二、attachEvent 與 addEventListener 的區(qū)別娄昆?
在早期 IE 瀏覽器中(如: IE 8)是不支持新標(biāo)準(zhǔn)的 addEvenlistener 方法的肉迫,但是提供了 attachEvent 方法來(lái)代替,所以這是 IE 兼容問(wèn)題稿黄。不過(guò)現(xiàn)在基本不再考慮這個(gè)兼容了,另外 IE 使用 detachEvent 來(lái)解綁事件跌造。以下詳細(xì)說(shuō)說(shuō)兩者的區(qū)別杆怕。
1. 事件機(jī)制
在老版的 IE 中,只支持 DOM0 級(jí)事件壳贪,也就是說(shuō)陵珍,只有事件的冒泡階段。而addEventListener()
是 DOM2 級(jí)事件违施,是一個(gè)由事件捕獲 => 目標(biāo)事件 => 事件冒泡 這樣的一個(gè)事件流。這也是為什么attachEvent()
沒(méi)有第三個(gè)參數(shù)的原因。
2. 事件對(duì)象
在attachEvent()
綁定的函數(shù)中宁仔,并沒(méi)有把對(duì)應(yīng)的目標(biāo)事件對(duì)象傳進(jìn)來(lái)飘言,所以只能通過(guò)window.event
來(lái)訪問(wèn)這個(gè)事件對(duì)象。
3. 事件中的 this
在attachEvent()
綁定的函數(shù)中辣往,沒(méi)有把事件觸發(fā)的對(duì)象作為 this 傳進(jìn)函數(shù)兔院,所以在attachEvent()
中直接使用 this 的話,是全局window
對(duì)象站削。
三坊萝、解釋 IE 事件冒泡和 DOM2 事件傳播機(jī)制?
- 事件冒泡
事件開(kāi)始時(shí)由最具體的元素接收,然后逐級(jí)向上傳播到較為不具體的元素
- DOM2 事件傳播機(jī)制
DOM2 級(jí)事件規(guī)定事件流包括三個(gè)階段十偶,事件捕獲階段菩鲜,處于目標(biāo)階段,事件冒泡階段惦积,首先發(fā)生的是事件捕獲接校,為截取事件提供機(jī)會(huì),然后是實(shí)際目標(biāo)接收事件荣刑,最后是冒泡階段
四馅笙、如何阻止事件冒泡? 如何阻止默認(rèn)事件厉亏?
要阻止事件冒泡董习,可以對(duì)傳進(jìn)來(lái)的事件執(zhí)行stopPropagation()
方法,這個(gè)方法取消事件進(jìn)一步捕獲或冒泡爱只,如
document.querySelector(element).addEventListener('click',function(e){
e.stopPropagation()
//這里開(kāi)始阻止后續(xù)的冒泡或者捕獲了
console.log('xxx')
})
要取消默認(rèn)事件皿淋,如點(diǎn)擊<a>
后的默認(rèn)跳轉(zhuǎn)行為或者是<form>
表單的提交行為,可以對(duì)事件執(zhí)行preventDefault()
方法恬试。
另外窝趣,直接使用return false
可以粗暴的阻止事件冒泡、捕獲和默認(rèn)事件训柴。
五哑舒、有如下代碼,要求當(dāng)點(diǎn)擊每一個(gè)元素li時(shí)控制臺(tái)展示該元素的文本內(nèi)容幻馁。不考慮兼容
<ul class="ct">
<li>這里是</li>
<li>饑人谷</li>
<li>前端6班</li>
</ul>
<script>
//todo ...
</script>
結(jié)果
<ul class="ct">
<li>這里是</li>
<li>饑人谷</li>
<li>前端6班</li>
</ul>
<script>
var lists = document.querySelectorAll('.ct li');
lists.forEach((item, index, arr) => {
item.addEventListener('click', function() {
console.log(this.innerText);
})
})
</script>
六洗鸵、 補(bǔ)全代碼,要求:
- 當(dāng)點(diǎn)擊按鈕開(kāi)頭添加時(shí)在
<li>
這里是</li>
元素前添加一個(gè)新元素仗嗦,內(nèi)容為用戶(hù)輸入的非空字符串膘滨; - 當(dāng)點(diǎn)擊結(jié)尾添加時(shí)在最后一個(gè)
<li>
元素后添加用戶(hù)輸入的非空字符串. - 當(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>
//你的代碼
</script>
結(jié)果
<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 input = document.querySelector('.ipt-add-content')
var addStartBtn = document.querySelector('#btn-add-start')
var addEndBtn = document.querySelector('#btn-add-end')
var ct = document.querySelector('.ct')
var lists = ct.querySelectorAll('li')
//開(kāi)頭添加
addStartBtn.addEventListener('click', function(){
if(input.value){
var newLi = document.createElement('li')
newLi.innerText = input.value
//為新添加的元素添加事件
consoleText(newLi)
ct.insertBefore(newLi, lists[0])
}else {
alert("輸入不能為空稀拐!")
}
})
//結(jié)尾添加
addEndBtn.addEventListener('click', function(){
if(input.value){
var newLi = document.createElement('li')
newLi.innerText = input.value
//為新添加的元素添加事件
consoleText(newLi)
ct.appendChild(newLi)
}else {
alert("輸入不能為空火邓!")
}
})
//添加點(diǎn)擊打印文字事件
function consoleText(element){
element.addEventListener('click', function(){
console.log(this.innerText)
})
}
//為初始的 li 添加點(diǎn)擊事件
lists.forEach((item, index, arr) => {
consoleText(item)
})
</script>
七、補(bǔ)全代碼德撬,要求:當(dāng)鼠標(biāo)放置在<li>
元素上铲咨,會(huì)在img-preview
里展示當(dāng)前<li>
元素的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>
結(jié)果
<ul class="ct">
<li data-img="https://img6.bdstatic.com/img/image/public/bizhi112.png">鼠標(biāo)放置查看圖片1</li>
<li data-img="http://img05.tooopen.com/images/20160121/tooopen_sy_155168162826.jpg">鼠標(biāo)放置查看圖片2</li>
<li data-img="http://img06.tooopen.com/images/20160728/tooopen_sy_172881922881.jpg">鼠標(biāo)放置查看圖片3</li>
</ul>
<img src="" alt="圖片" class="img-preview">
<script>
var lists = document.querySelectorAll('.ct li')
var img = document.querySelector('.img-preview')
lists.forEach((item) => {
item.addEventListener('mouseover', function(){
img.src = this.getAttribute('data-img')
})
})
</script>