1. 程式人生 > >憤怒的WebAPI(五)——事件

憤怒的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>