-
關(guān)鍵詞:事件
通過 “事件” 實現(xiàn)JavaScript和HTML的交互
1. DOM0事件和DOM2級在事件監(jiān)聽使用方式上有何區(qū)別?
事件處理程序(事件監(jiān)聽器)有以下幾種:
(1)HTML事件處理程序;(2)DOM0級事件處理程序;
(3)DOM2級事件處理程序;(4)IE事件處理程序;
(1)HTML事件處理程序
元素支持的每種事件,都可以使用一個HTML屬性來指定:該屬性與相應(yīng)事件處理程序同名;該屬性的值應(yīng)該是,可執(zhí)行的 JavaScript 代碼
本質(zhì):直接將事件添加至HTML結(jié)構(gòu)里的HTML元素上
在HTML事件處理程序中,可包含要執(zhí)行的具體動作,也可調(diào)用在頁面其它地方定義的腳本(封裝的函數(shù))
缺點(diǎn)
(1)HTML代碼和JS代碼緊密耦合,不便于維護(hù),所以不推薦使用
(2)當(dāng)事件處理程序未完成加載,此時用戶觸發(fā)事件,就會報錯(2)DOM0級事件處理程序
通過JS指定事件處理程序,這是一種傳統(tǒng)方式:將一個函數(shù),賦值給一個事件處理程序的屬性。這種方式具有跨瀏覽器的優(yōu)勢。
每個元素都有自己的事件處理程序?qū)傩?,這些屬性通常全部小寫,將這種屬性的值設(shè)置為一個函數(shù),就可以指定事件處理程序
一般步驟:這種添加事件的方法叫做DOM0級事件處理程序
1.在JS中取得元素對象
2.給元素對象添加事件屬性
3.給元素對象刪除事件屬性缺點(diǎn)
可同時綁定幾個不同的事件,但不能同時綁定多個相同的事件:圍繞同一事件只能添加一個事件處理程序,否則會發(fā)生覆蓋,最終結(jié)果只執(zhí)行最后一個事件處理程序(3)DOM2級事件處理程序
定義兩個方法專門用于添加事件處理程序(
addEventListener())和刪除事件處理程序(removeEventListener())所有的DOM節(jié)點(diǎn)都包含這兩個方法,并且它們都接受三個參數(shù):
1.事件類型, 2.事件處理程序的函數(shù), 3.布爾值(用于設(shè)置事件觸發(fā)階段:冒泡或捕獲)注意:此種方法存在兼容問題,IE8及以下不支持
好處:圍繞同一事件可添加多個事件處理程序,并按照事件被添加的順序觸發(fā)
(4)IE事件處理程序
IE實現(xiàn)了與DOM2級類似的兩個方法:添加事件處理程序(
attachEvent())和刪除事件處理程序(detachEvent())這兩個方法接受兩個參數(shù)
1.事件處理程序的名稱, 2.事件處理程序的函數(shù)
注:IE8及以下僅支持事件冒泡,所以不存在布爾值這個參數(shù)與上述三種事件處理程序不同,IE事件處理程序的
this指向window,而非被綁定事件的元素
2. addEventListener()與attachEvent()的區(qū)別?
- 1 接受參數(shù)數(shù)量不同
- addEventListener()接受三個參數(shù):1事件類型, 2事件處理方法, 3布爾參數(shù)
- attachEvent()接受兩個參數(shù):1事件處理程序名稱, 2事件處理程序方法
- 2 第一個參數(shù)意義不同
- addEventListener():第一個參數(shù)為 “事件類型” ,例如 click
- attachEvent():第一個參數(shù)為 “事件處理程序名稱” ,例如 onclick
- 3 事件處理程序的作用域不同
- addEventListener():作用域是元素本身,this是指的觸發(fā)元素
- attachEvent():作用域處于全局作用域下,this是window
- 4 為一個事件添加多個事件處理程序時,執(zhí)行順序不同
- addEventListener():按照添加順序執(zhí)行
- attachEvent():執(zhí)行順序無規(guī)律
3. 解釋IE事件冒泡和DOM2事件傳播機(jī)制?
- 事件:是文檔或瀏覽器窗口中發(fā)生的,特定的交互瞬間(HTML 和 JS 都是通過事件進(jìn)行交互)
- 事件流:描述的是從頁面中接受事件的順序——
事件發(fā)生時,會在元素節(jié)點(diǎn)(觸發(fā)源)與整個文檔節(jié)點(diǎn)之間按照特定的順序傳播,
事件所經(jīng)過的路徑上的所有節(jié)點(diǎn)都會感知到該事件,這個傳播過程即 DOM 事件流。
- 事件流傳播順序
- IE事件冒泡:事件最開始,由最具體的元素接收(文檔中嵌套層次最深的那個節(jié)點(diǎn)),然后逐級向上傳播至最不具體的那個節(jié)點(diǎn)(document 文檔)
- Netscape事件捕獲:事件最開始,不太具體的節(jié)點(diǎn)應(yīng)該更早接收到事件,而最具體的節(jié)點(diǎn)最后接收到事件
- DOM2事件流:由事件捕獲和事件冒泡共同組成
首先,按照事件捕獲階段順序傳播(不太具體節(jié)點(diǎn) → 最具體節(jié)點(diǎn))
其次,事件到達(dá)目標(biāo)元素階段(經(jīng)過第一次傳播,到達(dá)具體節(jié)點(diǎn))
最后,按照事件冒泡階段順序傳播(最具體節(jié)點(diǎn) → 不太具體節(jié)點(diǎn))

4. 如何阻止事件冒泡? 如何阻止默認(rèn)事件?
- 阻止冒泡
- 阻止冒泡,相當(dāng)于攔截事件:在某個節(jié)點(diǎn)終止事件傳播,致使傳播路徑上該節(jié)點(diǎn)的后續(xù)元素?zé)o法感知到該事件
- DOM中:可以調(diào)用方法
stopPropagation() - IE中:可以進(jìn)行賦值:
cancelBubble(默認(rèn)為false,設(shè)置為true后可以取消事件冒泡) - 阻止默認(rèn)事件
- 與轉(zhuǎn)義符號的功能有些相似,即:使目標(biāo)自身的特殊功能失效
- DOM中:可以調(diào)用方法
preventDefault() - IE中:可以進(jìn)行賦值:
returnValue(默認(rèn)為true,設(shè)為false可以取消事件默認(rèn)行為)
5. 補(bǔ)全JS代碼
-
要求當(dāng)點(diǎn)擊每一個元素li時控制臺展示該元素的文本內(nèi)容(不考慮兼容)
-
思路:為目標(biāo)元素添加事件處理程序,當(dāng)發(fā)生事件時,執(zhí)行對應(yīng)函數(shù)
-
示例預(yù)覽
<ul class="ct">
<li>這里是</li>
<li>饑人谷</li>
<li>前端6班</li>
</ul>
<script>
// 代碼補(bǔ)全,可有兩種方法實現(xiàn),1事件代理,2循環(huán)遍歷
// ----------------------此處使用事件代理--------------------------
// 獲取DOM節(jié)點(diǎn)
var ct = document.querySelector('.ct');
// 使用事件代理,對容器添加事件處理程序
ct.addEventListener('click', function (e) {
// 判斷觸發(fā)源,防止容器觸發(fā)事件導(dǎo)致不正常效果
if(clickNode.tagName.toLowerCase() === 'li'){
// 控制臺打印觸發(fā)源的文本內(nèi)容
console.log(e.target.innerText);
}
})
</script>
6. 補(bǔ)全JS代碼
-
當(dāng)點(diǎn)擊按鈕
開頭添加時在第一個li元素前添加一個新元素 -
當(dāng)點(diǎn)擊按鈕
結(jié)尾添加時在最后一個li 元素后添加一個新元素 -
當(dāng)點(diǎn)擊每一個元素li時控制臺展示該元素的文本內(nèi)容。
-
思路:1創(chuàng)建一個新元素;2獲取用戶輸入;3添加元素到頁面指定位置
-
示例預(yù)覽:輸入內(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>
// 代碼補(bǔ)全
// ------------------------------------------------------------------
// 獲取DOM節(jié)點(diǎn)
var ct = document.querySelector('.ct'),
ipt = document.querySelector('.ipt-add-content'),
start = document.querySelector('#btn-add-start'),
end = document.querySelector('#btn-add-end');
// 為 按鈕:開頭添加 綁定事件處理程序
start.addEventListener('click', function(){
// 思路:1創(chuàng)建一個新元素 2獲取用戶輸入 3添加元素到頁面指定位置
var li = document.createElement('li');
li.innerText = iptAddContent.value;
ct.insertBefore(li, ct.firstChild);
})
// 為 按鈕:結(jié)尾添加 綁定事件處理程序
end.addEventListener('click', function(e){
var li = document.createElement('li');
li.innerText = iptAddContent.value;
ct.appendChild(li);
})
// 使用事件代理,添加事件處理程序
ct.addEventListener('click', function(e){
if(e.target.tagName.toLowerCase() === 'li'){
console.log(e.target.innerText);
}
})
</script>
7. 補(bǔ)全代碼
-
要求:當(dāng)鼠標(biāo)放置在 li元素 上,會在 img-preview 里展示當(dāng)前 li元素 的 data-img 對應(yīng)的圖片
-
思路:1獲得觸發(fā)源的 data-img 屬性值;2組裝HTML結(jié)構(gòu)放到指定位置
-
示例預(yù)覽
<ul class="ct">
<li data-img="1.jpg">鼠標(biāo)放置查看圖片1</li>
<li data-img="2.jpg">鼠標(biāo)放置查看圖片2</li>
<li data-img="3.jpg">鼠標(biāo)放置查看圖片3</li>
</ul>
<div class="img-preview"></div>
<script>
// 代碼補(bǔ)全
// ------------------------------------------------------------------
// 獲取DOM節(jié)點(diǎn)
var ct = document.querySelector('.ct');
var panal = document.querySelector('.img-preview');
// 使用事件代理,對 li 元素 添加事件處理程序
ct.addEventListener('mouseover', function(e){
if(e.target.tagName.toLowerCase() === 'li'){
// 思路:1獲得觸發(fā)源的 data-img 屬性值;2組裝HTML結(jié)構(gòu)放到指定位置【本質(zhì)為tab切換,也可使用for循環(huán)+增減display值來實現(xiàn)】
var dataImg = e.target.getAttribute('data-img');
panal.innerHTML = '  ' // 字符串拼接
}
})
</script>