憤怒的WebAPI(五)——事件
一、普通事件設定與移除
1、普通事件採用的是屬性儲存方式,所以會出現覆蓋的問題。
<button id="btn">按鈕</button>
<script>
var btn = document.getElementById('btn');
btn.onclick = function () {
console.log('這是一個點選事件');
};
btn.onclick = function () {
console.log('這是新的點選事件程式碼');
</script>
2、普通事件的移除
btn.onclick = null;
設定某個事件為null即可(理論上來說,設定任意的非函式值即可,但是null較為規範)。
二、事件繫結
1、元素.addEventListener() - 新增事件監聽(事件繫結)
引數1:事件型別,沒有on
引數2:事件處理程式,函式
好處:可以避免事件的覆蓋問題。
<button id="btn">按鈕</button> <script> var btn = document.getElementById('btn'); btn.addEventListener('click', function () { console.log('這是事件程式碼1'); }); function fun () { console.log('這是事件程式碼2'); } btn.addEventListener('click', fun); </script>
2、移除方式:removeEventListener()
引數必須與設定時完全相同(注意:事件處理程式必須是同一個函式,通常採用命名函式形式即可)。
btn.removeEventListener('click', fun);
對我們來說,最致命的話不是愛過,而是我們要相容IE
3、ie中的事件操作
btn.attachEvent('onclick', function () { console.log('這是點選事件'); }); function fun () { console.log('這是點選事件'); } btn.attachEvent('onclick', fun); // detachEvent() - 移除事件 btn.detachEvent('onclick', fun);
三、事件捕獲
1、事件冒泡
① 某個元素的事件觸發後,可能不僅觸發當前元素事件,還會觸發其他元素的事件。
② 事件的預設傳遞方式稱為,事件冒泡。
③ 傳遞規則(從內向外):當前元素觸發後,觸發自身事件,並且將事件傳遞給父元素如果父元素具有相同型別的事件時,也可以被觸發。以此類推。
2、事件捕獲
① 設定方式:使用addEventListener()的引數3,布林型別,預設為false,表示事件冒泡,true表示事件捕獲執行。
② 執行順序:與事件冒泡執行順序相反,從外向內。
3、事件執行的三個階段
① 捕獲階段
② 當前目標階段
③ 冒泡階段
④ 如果多個事件中,同時設定了事件冒泡和事件捕獲,先是事件捕獲執行,然後是當前目標執行,最後事件冒泡執行,通常情況下我們只使用事件冒泡
四、事件物件
事件操作中,有許多資訊會被js的事件機制整理好之後,採用一個物件儲存,傳遞給我們,這個物件就是事件物件。
1、接收方式
① 在事件處理程式的引數位置接收
② ie中使用window.event接收
e = e || window.event;
// 相容處理
2、type屬性
利用事件物件的type屬性進行檢測,可以使用一個函式對多個事件進行統一管理。
<button id="btn">按鈕</button>
<script>
var btn = document.getElementById('btn');
btn.onclick = fun;
btn.onmouseover = fun;
function fun (e) {
if (e.type === 'click') {
console.log('這是點選事件程式碼');
} else if (e.type === 'mouseover') {
console.log('這是移入事件程式碼');
}
}
</script>
五、事件委託
事件委託經常使用,一定要會,一定要!
事件冒泡的使用場景——事件委託:將內部元素的事件,設定給了某個祖先元素,事件中通過一些檢測,讓內部的某些元素觸發效果。
為啥要使用事件委託捏?主要是因為用js動態建立的子元素是沒有事件的,我們必須重新繫結事件,用事件委託就不用重新繫結。再者,用事件委託可以大大地提高程式碼的效能,十個子元素需要與DOM互動十次,如果子元素事件委託給了父元素,只需要父元素與DOM互動一次,程式碼的效能自然就提高了。
<div id="box">
<h4 class="title">這是h4</h4>
<p>這是box中原始的p標籤</p>
<p>這是box中原始的p標籤</p>
<p>這是box中原始的p標籤</p>
<span>這是span</span>
</div>
<button id="btn">按鈕</button>
<script>
var box = document.getElementById('box');
var ps = box.children; // 獲取所有p標籤
var btn = document.getElementById('btn');
btn.onclick = function () {
// 給box內部動態建立元素,設定一個新的p標籤
var p = document.createElement('p');
p.innerText = '這是新的p標籤';
box.appendChild(p);
};
// 出現的問題:希望給box中所有的p標籤新增事件,但是動態建立的元素無法使用這個事件。
box.onclick = function (e) {
// 將事件設定給box後,雖然所有p標籤均可使用事件,但是box自身和內部的其他元素也可以觸發這個事件。我們只需要在box的事件內部設定一些判斷規則即可,例如,這個觸發的元素是不是p標籤
// 事件物件的屬性target,用於獲取真正觸發事件的元素
// console.log(e.target);
// 根據需求,進行任意的檢測操作即可:
if (e.target.nodeName === 'P') {
console.log('這是p標籤的對應操作');
} else if (e.target.nodeName === 'SPAN') {
console.log('這是span標籤的對應操作');
} else if(e.target.className === 'title') {
console.log('這是類名為title的元素操作');
}
};
</script>
關於表格的小案例
<style>
* {
margin: 0;
padding: 0;
}
table {
width: 600px;
border-collapse: collapse;
}
thead {
background-color: #e5e5e5;
}
tbody {
text-align: center;
}
tbody td {
width: 165px;
height: 19px;
}
</style>
<div id="box">
</div>
<script>
//建立表格資料
//表頭的資料 建立th使用
var heads = ["姓名", "科目", "成績", "操作"];
//根據datas中物件的個數建立tr行,每個行中的td個數就是這個物件的屬性個數
var datas = [
{"name": "張三1", "subject": "語文1", "score": 99.8},
{"name": "張三2", "subject": "語文2", "score": 80.8},
{"name": "張三3", "subject": "語文3", "score": 70.8},
{"name": "張三4", "subject": "語文4", "score": 100},
{"name": "張三5", "subject": "語文5", "score": 60},
{"name": "張三6", "subject": "語文6", "score": 70},
{"name": "張三7", "subject": "語文7", "score": 89.8}
];
// 步驟:
// 1 明確資料的含義
// 2 建立基本結構
// 3 根據資料進行結構建立
//1.’獲取元素
var box = document.getElementById('box');
// 2.建立table、thead、tbody
var table = crt('table', box);
table.border = '1';
var thead = crt('thead', table);
var tbody = crt('tbody', table);
// 3 建立thead中的結構
var tr = crt('tr', thead);
for(var i = 0; i < heads.length; i++) {
var th = crt('th', tr);
th.innerText = heads[i];
}
// 4 根據datas中的資料進行tbody中結構的建立 - 課後練習
for(i = 0; i < datas.length; i++) {
tr = crt('tr', tbody);
for(var k in datas[i]) {
var td = crt('td', tr);
td.innerText = datas[i][k];
}
// 5 在每個tr最後單獨設定一個td,內部放置一個刪除按鈕
td = crt('td', tr);
td.innerHTML = '<a href="javascript:;">刪除</a>';
td.children[0].onclick = function () {
var tr = this.parentNode.parentNode;
var trs = tbody.children;
for (var i = 0; i < trs.length; i++) {
if (trs[i] === tr) {
datas.splice(i,1);
break;
}
}
tbody.removeChild(tr);
}
}
function crt (tagName, target) {
var ele = document.createElement(tagName);
target.appendChild(ele);
return ele;
}
</script>