1.DOM0 事件和DOM2級(jí)在事件監(jiān)聽(tīng)使用方式上有什么區(qū)別?
- DOM0事件有兩種:
- 一是在標(biāo)簽內(nèi)寫(xiě)onclick事件
- 二是在js寫(xiě)node.onclick = function() {};
第二種方法事件處理程序被認(rèn)為是元素的方法,事件處理程序在元素的作用域下運(yùn)行刁憋,所以同一執(zhí)行上下文中只能存在一種事件處理程序迎捺。
- DOM2級(jí)事件定義了兩個(gè)方法用于處理指定和刪除事件處理程序的操作:
- addEventListener
- removeEventListener
- 所有的DOM節(jié)點(diǎn)都包含這兩個(gè)方法吠勘,并且它們都接受三個(gè)參數(shù):
- 事件類(lèi)型
- 事件處理方法
- 布爾參數(shù)币厕,如果是true表示在捕獲階段調(diào)用事件處理程序曹宴,如果是false城榛,則是在事件冒泡階段處理
- DOM2級(jí)事件規(guī)定事件流包括三個(gè)階段揪利,事件捕獲階段,處于目標(biāo)階段狠持,事件冒泡階段疟位,首先發(fā)生的是事件捕獲,為截取事件提供機(jī)會(huì)喘垂,然后是實(shí)際目標(biāo)接收事件甜刻,最后是冒泡階段
DOM2級(jí)事件的兩個(gè)方法好處在于在元素作用域下同一執(zhí)行上下文中可以存在多個(gè)事件處理程序
2.attachEvent與addEventListener的區(qū)別绍撞?
- 添加事件處理程序事addEventListener和attachEvent主要有幾個(gè)區(qū)別:
- 參數(shù)個(gè)數(shù)不相同,這個(gè)最直觀得院,addEventListener有三個(gè)參數(shù)傻铣,attachEvent只有兩個(gè),attachEvent添加的事件處理程序只能發(fā)生在冒泡階段祥绞,addEventListener第三個(gè)參數(shù)(true/false)可以決定添加的事件處理程序是在捕獲階段還是冒泡階段處理(我們一般為了瀏覽器兼容性都設(shè)置為冒泡階段)
- 第一個(gè)參數(shù)意義不同非洲,addEventListener第一個(gè)參數(shù)是事件類(lèi)型(比如click,load)蜕径,而attachEvent第一個(gè)參數(shù)指明的是事件處理函數(shù)名稱(chēng)(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í)順序無(wú)規(guī)律(添加的方法少的時(shí)候大多是按添加順序的反順序執(zhí)行的戚扳,但是添加的多了就無(wú)規(guī)律了)忧便,所以添加多個(gè)的時(shí)候,不依賴(lài)執(zhí)行順序的還好帽借,若是依賴(lài)于函數(shù)執(zhí)行順序珠增,最好自己處理,不要指望瀏覽器
3. 解釋IE事件冒泡和DOM2事件傳播機(jī)制砍艾?
- IE事件冒泡的流程是蒂教,當(dāng)監(jiān)測(cè)到一個(gè)事件發(fā)生時(shí),事件會(huì)從目標(biāo)元素開(kāi)始向父級(jí)傳遞脆荷,直到傳遞到window(document)停止凝垛。這期間,如果遇到同樣的事件蜓谋,都會(huì)激活對(duì)應(yīng)的事件處理程序梦皮。
- DOM2的時(shí)間傳播機(jī)制包括了事件冒泡機(jī)制作為事件傳播的第三階段,并且加入了第一階段:事件捕獲桃焕,即與冒泡機(jī)制相反剑肯,偵聽(tīng)到事件時(shí),事件先從document開(kāi)始再到子元素一層層直到目標(biāo)元素观堂。第二階段: 處于目標(biāo)階段让网,此時(shí)事件在div上發(fā)生岖妄,被看做冒泡的一部分。
在兼容所有瀏覽器的事件處理程序上主要采用冒泡機(jī)制作為事件傳播機(jī)制寂祥。
同時(shí)也衍生出了解決當(dāng)需要在父元素下進(jìn)行新增的子元素的操作所造成無(wú)法觸發(fā)事件或者事件方法復(fù)雜的技巧荐虐,如:
<body>
<ul>
<li>01</li>
<li>02</li>
<li>03</li>
</ul>
<script type="text/javascript">
function $(id) {
return document.querySelector(id);
}
$('ul').addEventListener('click', function(e) {
if(e.target.tagName.toLowerCase() === 'li') {
console.log(e.target.innerHTML);
}
});
</script>
</body>
4.如何阻止事件冒泡? 如何阻止默認(rèn)事件丸凭?
-
阻止事件冒泡
<body> <ul> <li>01</li> <li>02</li> <li>03</li> </ul> <script type="text/javascript"> function $(id) { return document.querySelector(id); } function $$(id) { return document.querySelectorAll(id); } [].forEach.call($$('li'), function(node) { node.addEventListener('click', function(e) { e.stopPropagation(); //阻止事件冒泡方法 console.log(e.target.innerHTML); }); }) //當(dāng)父元素也設(shè)置了點(diǎn)擊事件時(shí)福扬,點(diǎn)擊子元素也會(huì)觸發(fā)父元素事件處理程序 $('ul').addEventListener('click',function(e) { console.log(e.target); }) </script> </body>
-
阻止默認(rèn)事件
<body>
<a >饑人谷官網(wǎng)</a><script type="text/javascript"> function $(id) { return document.querySelector(id); } $('a').addEventListener('click', function(e) { e.preventDefault(); console.log('阻止跳轉(zhuǎn)...') }) </script> </body>
5.有如下代碼,要求當(dāng)點(diǎn)擊每一個(gè)元素li時(shí)控制臺(tái)展示該元素的文本內(nèi)容惜犀。不考慮兼容
<ul>
<li>這里是</li>
<li>饑人谷</li>
<li>前端6班</li>
</ul>
<script type="text/javascript">
$('ul').addEventListener('click',function(e){
if(e.target.tagName.toLowerCase() === 'li') {
console.log(e.target.innerHTML);
}
})
function $(id) {
return document.querySelector(id);
}
function $$(id) {
return document.querySelectorAll(id);
}
</script>
6.補(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 type="text/javascript"> var content = $('.ipt-add-content'); var btnStart = $('#btn-add-start'); var btnEnd = $('#btn-add-end'); $('ul').addEventListener('click',function(e){ if(e.target.tagName.toLowerCase() === 'li') { console.log(e.target.innerHTML); } }); btnStart.addEventListener('click',function(){ var addLi = document.createElement('li'); if(content.value) { addLi.innerHTML = content.value; $('ul').insertBefore(addLi,$('ul').children[0]); }else{ console.log('請(qǐng)?zhí)顚?xiě)內(nèi)容后再添加!') } }); btnEnd.addEventListener('click',function(){ var addLi = document.createElement('li'); if(content.value) { addLi.innerHTML = content.value; $('ul').appendChild(addLi); }else{ console.log('請(qǐng)?zhí)顚?xiě)內(nèi)容后再添加莉御!') } }); function $(id) { return document.querySelector(id); } function $$(id) { return document.querySelectorAll(id); } </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="http://cdn.jirengu.com/book.jirengu.com/img/11.jpg">鼠標(biāo)放置查看圖片1</li>
<li data-img="http://cdn.jirengu.com/book.jirengu.com/img/13.jpg">鼠標(biāo)放置查看圖片2</li>
<li data-img="http://cdn.jirengu.com/book.jirengu.com/img/14.jpg">鼠標(biāo)放置查看圖片3</li>
</ul>
<div class="img-preview"></div>
<script type="text/javascript">
var ulCt = $('.ct');
var preview = $('.img-preview');
ulCt.addEventListener('mouseover',function(e){
if(e.target.tagName.toLowerCase() === 'li') {
// console.log(e.toElement.getAttribute('data-img'))
var address = e.toElement.getAttribute('data-img')
var imgPreview = document.createElement('img');
imgPreview.setAttribute('src',address);
preview.appendChild(imgPreview);
}
});
ulCt.addEventListener('mouseout',function(e){
if(e.target.tagName.toLowerCase() === 'li') {
preview.innerHTML = '';
}
});
function $(id) {
return document.querySelector(id);
}
function $$(id) {
return document.querySelectorAll(id);
}
</script>
8.事件兼容處理程序(github)
function binEvent(node,type,handler) {
node['e' + type + handler] = handler;
node[type + handler] = function(){
node['e' + type + handler](window.event)
}
node.attachEvent('on' + type,node[type + handler]);
}
- 編寫(xiě)兼容IE上巧妙的運(yùn)用了閉包和引用類(lèi)型的特性牍颈,使用閉包將變量保存在引用類(lèi)型數(shù)據(jù)地址中,而引用類(lèi)型則是只要找到指針就可以找到對(duì)應(yīng)存放數(shù)據(jù)的地址琅关,不會(huì)像非引用類(lèi)型一樣數(shù)據(jù)改變而改變煮岁。