天天看點

JavaScript_事件事件概述事件的執行機制

文章目錄

  • 事件概述
    • 什麼是事件
    • 事件對象
    • 點選事件的光标坐标的擷取
      • 相對于你點選的元素
      • 相對于浏覽器可視視窗你點選的坐标點
      • 相當于頁面你點選的坐标點
    • 點選按鍵資訊(了解)
    • 常見的事件(了解)
      • 浏覽器事件
      • 滑鼠事件
      • 鍵盤事件
      • 表單事件
      • 觸摸事件
    • 鍵盤事件
      • 确定按鍵
      • 常見的鍵盤碼(了解)
      • 組合按鍵
    • 事件的綁定方式
      • 事件監聽
      • 兩個方式的差別
  • 事件的執行機制
    • 事件的傳播
    • 冒泡、捕獲、目标
      • 目标
      • 冒泡
      • 捕獲
      • 冒泡和捕獲的差別
    • 事件委托
      • 事件觸發
      • target
      • 委托
      • 總結
    • 預設行為
      • 阻止預設行為

事件概述

什麼是事件

  • 一個事件由什麼東西組成?
    • 觸發誰的事件:事件源
    • 觸發什麼事件:事件類型
    • 觸發以後做什麼:事件處理函數
var oDiv = document.querySelector('div');

oDiv.onclick = function(){
	//誰來觸發事件 => oDiv => 這個事件的事件源就是oDiv
	//觸發什麼事件 => onclick => 這個事件類型就是cLick
	//觸發之後做什麼 => function(){} => 這個事件的處理函數
}
           
  • 我們想要在點選 div 以後做什麼事情,就把我們要做的事情寫在事件處理函數裡面
var oDiv = document.querySelector('div');

oDiv.onclick = function(){
	console.log('你點選了div');
}
           
- 當我們點選 div 的時候,就會執行時間函數内部的代碼
- 每當點選一次,就會執行一次事件處理函數
           

事件對象

  • 什麼是事件對象?
  • 就是當你觸發一個事件以後,對該事件的一些描述資訊
  • 例如:
    • 你觸發一個點選事件的時候,你點在哪個位置了,坐标是多少
    • 你觸發了一個鍵盤事件的時候,你按的是哪個按鈕
    • 。。。。。
  • 每一個事件都會有一個對應的對象來描述這些資訊,我們就把這個對象叫做事件對象
  • 浏覽器給了我們應該黑盒子,叫做

    window.event

    ,就是對事件資訊的所有描述
    • 比如點選事件
    • 你點在了

      0,0

      位置,那麼你得到的這個事件對象裡面對應的就會有一個點位的屬性
    • 你點在了

      10,10

      位置,那麼你得到的這個事件對象裡面對應的就會有這個點位的屬性
    • 。。。
oDiv.onclick = function(){
	console.log(window.event.X軸坐标點資訊);
	console.log(window.enent.Y軸坐标點資訊);
}
           
  • 這玩意很好用,但是一般來說,好用的東西就會有相容性問題
  • IE低版本

    裡面這個東西好用,但是在

    高版本IE

    Chrome

    裡面不好使了
  • 我們就得用另一種方式來擷取事件對象
  • 在每一個事件處理函數的形參位置,預設第一個就是事件對象
oDiv.onclick = function (e){
	// e 就是和IE的window.event 一樣的東西
	console.log(e.X軸的坐标點資訊);
	console.log(e.Y軸坐标點資訊);
}
           
  • 綜上所述,我們以後每一個事件裡面,想要擷取事件對象的時候,都用相容寫法
oDiv.onclick = function(e){
	e = e || window.event;
	console.log(e.X軸坐标點的資訊);
	console.log(e.Y軸坐标點的資訊);
}
           

點選事件的光标坐标的擷取

  • 剛才既然說了,可以擷取到坐标點,那麼接下來我們就學習一下怎麼擷取坐标點
  • 我們的每一個點選事件的坐标點都不是一對,因為要有一個相對的坐标系
  • 例如:
    • 相對事件源(你點選的元素)
    • 相對頁面
    • 相對浏覽器視窗
    • 。。。。。
  • 因為都不一樣,是以我們擷取的事件對象裡面的屬性也不一樣

相對于你點選的元素

  • offsetX

    offsetY

  • 是相對于你點選的元素的邊框内側開始計算
<style>
  * {
    margin: 0;
    padding: 0;
  }

  div {
    width: 300px;
    height: 300px;
    padding: 20px;
    border: 10px solid #333;
    margin: 20px 0 0 30px;
  }
</style>
<body>
  <div></div>

  <script>
    var oDiv.document.qerySelector('div');
	//注冊點選事件
	oDiv.onclick = function(e){
		//事件對象相容寫法
		e = e || window.event;
		console.log(e.offsetX);
		console.log(e.offsetY);
	}
  </script>
</body>
           
JavaScript_事件事件概述事件的執行機制

相對于浏覽器可視視窗你點選的坐标點

  • clientX

    clientY

  • 是相當于浏覽器視窗來計算的,不管你頁面滾動到什麼情況,都是根據可視視窗來計算坐标
<style>
  * {
    margin: 0;
    padding: 0;
  }

  body {
    width: 2000px;
    height: 2000px;
  }

  div {
    width: 300px;
    height: 300px;
    padding: 20px;
    border: 10px solid #333;
    margin: 20px 0 0 30px;
  }
</style>
<body>
  <div></div>

  <script>
    var oDiv = document.querySelector('div');

	//注冊點選事件
	oDiv.onclick = function(e){
		//事件對象相容寫法
		e = e || window.event;
		console.log(e.clientX);
		console.log(e.clientY);
	}
  </script>
</body>
           

相當于頁面你點選的坐标點

  • pageX

    pageY

  • 是相對于整個頁面的坐标點,不管有沒有滾動,都是相對于頁面拿到的坐标點
<style>
  * {
    margin: 0;
    padding: 0;
  }

  body {
    width: 2000px;
    height: 2000px;
  }

  div {
    width: 300px;
    height: 300px;
    padding: 20px;
    border: 10px solid #333;
    margin: 20px 0 0 30px;
  }
</style>
<body>
  <div></div>

  <script>
    var oDiv = document.querySelector('div');
    //注冊點選事件
    oDiv.onclick = function(e){
    //事件對象相容寫法
    e = e || window.event;
    console.log(e.pageX);
    console.log(e.pageY);
    }
  </script>
</body>
           

點選按鍵資訊(了解)

  • 我們的滑鼠一般都有兩個按鍵,一個左鍵一個右鍵
  • 我們的事件對象裡面也有一個資訊,确定你點選的是左鍵還是右鍵
  • 我們使用

    事件對象.button

    來擷取資訊
  • 為滑鼠左鍵,

    2

    為滑鼠右鍵

常見的事件(了解)

  • 我們在書寫頁面的時候經常用到的一些事件
  • 大緻分為幾類,浏覽器事件、滑鼠事件、鍵盤事件、表單事件、觸摸事件
  • 不需要都記住,但是大概要知道

浏覽器事件

  • load

    :頁面全部資源加載完畢
  • scroll

    :浏覽器滾動的時候觸發
  • 。。。

滑鼠事件

  • click

    :點選事件
  • dblclick

    :輕按兩下事件
  • contextmenu

    :滑鼠右鍵單擊事件
  • mousedown

    :滑鼠左鍵按下事件
  • mouseup

    :滑鼠左鍵擡起事件
  • mousemove

    :滑鼠移動事件
  • mouseover

    :滑鼠移入事件
  • mouseout

    :滑鼠移出事件
  • mouseenter

    :滑鼠移入事件
  • mouseleave

    :滑鼠移出事件
  • 。。。。

鍵盤事件

  • keyup

    :鍵盤擡起事件
  • keydown

    :鍵盤按下事件
  • keypress

    :鍵盤按下再擡起事件
  • 。。。。

表單事件

  • change

    :表單内容改變事件
  • input

    :表單内容輸入事件
  • submit

    :表單送出事件
  • 。。。。

觸摸事件

  • touchstart

    :觸摸開始事件
  • touchend

    :觸摸結束事件
  • touchmove

    :觸摸移動事件
  • 。。。

鍵盤事件

  • 剛才了解了一下滑鼠事件,現在來聊聊鍵盤事件
  • 我們在鍵盤事件裡面最主要的就是要做兩個事情
    • 判斷點選是哪個按鍵
    • 有沒有組合按鍵,shift+a/ctrl+b
  • 我們先要明确一個問題,就是是不是所有元素都可以綁定鍵盤事件
    • 我們說事件有一個關鍵的東西是,該事件是由誰來觸發的
    • 一個 div 元素在頁面上,我怎麼能讓一個鍵盤事件觸發在 div 上
    • 是以說,我們一般隻給能在頁面上選中的元素(表單元素)和

      document

      來綁定鍵盤事件
oInput.onkeyup =function(){};
document.onkeyup = function(){};
           

确定按鍵

  • 我們的鍵盤上每一個按鍵都有一個自己獨立的編碼
  • 我們就是靠這個編碼來确定我們按下的是哪個按鍵的
  • 我們通過

    事件對象.keyCode

    或者

    事件對象.which

    來擷取
  • 為什麼要有兩個呢,是因為Firefox2.0不支援

    keycode

    是以要使用

    which

document.keyup = function(e){
	//事件對象的相容寫法
	e = e || window.event;
	//擷取鍵盤碼的相容寫法
	var keyCode = e.keyCode || e.which;
	console.log(keyCode);
}
           

常見的鍵盤碼(了解)

  • 8:删除鍵(delete)
  • 9:制表符(tab)
  • 13:Enter鍵(ebter)
  • 16:上檔鍵(shift)
  • 17:Ctrl鍵
  • 18:alt鍵
  • 27:取消鍵(esc)
  • 32:空格鍵(space)
  • 。。。

組合按鍵

  • 組合按鍵最主要的就是

    alt、shift、Ctrl

    三個按鍵
  • 在我點選某一個按鍵的時候判斷一下這三個鍵有沒有按下,有就是組合了,沒有就是沒組合
  • 事件對象裡面也為我們提供了三個屬性
    • altKey

      :alt 鍵按下得到true,否則得到false
    • shiftKey

      :shift 鍵按下得到 true,否則得到 false
    • ctrlKey

      :ctrl 鍵按下得到 true,否則得到 false;
  • 我們就可以通過這三個屬性來判斷是否按下了
document.onkeyup = function(e){
	e = e || window.event;
	keyCode = e.keyCode || e.which;
	if(e.altKey && keyCode === 65){
		console.log("你同時按下了 alt 和 a");
	}
}
           

事件的綁定方式

  • 我們現在給一個注冊事件都是使用

    onxxx

    的方式
  • 但是這個方式不是很好,隻能給一個元素注冊一個事件
  • 一旦寫了第二個事件,那麼第一個就被覆寫了
oDiv.onclick = function(){
	console.log('我是第一個事件');
}
oDiv.onclick = function(){
	console.log('我是第二個事件');
}
           
- 當你點選的時候,隻會執行第二個,第一個就沒有了
           
  • 我們還有一種事件監聽的方式給元素綁定事件
  • 使用

    addEventListener

    的方式添加
    • 這個方法不相容,在IE裡面要使用

      attachEvent

事件監聽

  • addEventListener

    :非IE 7、8使用
  • 文法:

    元素.addEventListener('事件類型',事件處理函數,冒泡還是補貨);

oDiv.addEventListener('click',function(){
	console.log('我是第一個事件');
},false)
oDiv.addEventListenner('click',function(){
	console.log('我是第二個事件');
},false)
           
- 當你點選 div 的時候,兩個函數都會執行,标簽會按照你注冊的順序執行
- 先列印`我是第一個事件`再列印`我是第二個事件`
- 注意:事件的類型不要寫on,點選事件就是click,不是onclick
           
  • attchEvent

    :IE 7 8下使用
  • 文法:

    元素.attachEvent('事件類型',事件處理函數);

oDiv.attachEvent('onclick',function(){
	console.log("我是第一個事件");
})
oDiv.attackEvent('onclick',function(){
	console.log('我是第二個事件');
})
           
- 當你點選div 的時候,兩個函數都會執行,并且會按照你注冊的順序倒叙執行
- 先列印 我是第二個事件 再列印 我是第一個事件
- 注意:事件類型要寫on,點選事件就寫onclick
           

兩個方式的差別

  • 注冊事件的時候事件類型參數的書寫
    • addEventListener

      :不用寫on
    • attachEvent

      :要寫on
  • 參數個數
    • addEventListener

      :一般是3個常用參數
    • attachEvent

      :2個參數
  • 執行順序
    • addEventListener

      :順序注冊,順序執行
    • attachEvent

      :順序注冊,倒叙執行
  • 适用浏覽器
    • addEventListener

      :非IE 7 8的浏覽器
    • attachEvent

      :IE 7 8浏覽器

事件的執行機制

  • 什麼是事件的執行機制呢?
    • 思考一個問題:
    • 當一個大盒子嵌套一個小盒子的時候,并且兩個盒子都有點選事件
    • 你點選裡面的小盒子,外面的大盒子上的點選事件要不要執行
JavaScript_事件事件概述事件的執行機制
JavaScript_事件事件概述事件的執行機制

事件的傳播

  • 就像上面那個圖檔一樣,我們點選在紅色盒子身上的同時,也是點選在了粉色盒子上
  • 這個是既定事實,那麼兩個盒子的點選事件都會觸發
  • 這個就叫做 事件的傳播
    • 當元素觸發一個事件的時候,其父元素也會觸發相同的事件,父元素的父元素也會觸發相同的事件
    • 就像上面的圖檔一樣
    • 點選在紅色盒子上的時候,會觸發紅色盒子的點選事件
    • 也是點選在了粉色的盒子上,也會觸發粉色盒子的點選事件
    • 也是點選在了 body 上,也會觸發 body 的點選事件
    • 也是點選在了 html 上,也會觸發 html 的點選事件
    • 也是點選在了 document 上,也會觸發 document 的點選事件
    • 也是點選在了 window 上,也會觸發 window 的點選事件
    • 也就是說,頁面上任何一個元素觸發事件,都會一層一層最終導緻 window 的相同僚件觸發,前提是各層級元素得有注冊相同的事件,不然不會觸發
  • 在事件傳播的過程中,有一些注意的點:
    • 隻會傳播同類事件
    • 隻會從點選元素開始按照 html 的結構逐層向上元素的事件會被觸發
    • 内部元素不管有沒有該事件,隻要上層元素有該事件,那麼上層元素的事件就會被觸發
  • 到現在,我們已經了解了事件的傳播,我們再來思考一個問題
    • 事件确實會從自己開始,到 window 的所有相同僚件都會觸發
    • 是因為我們點在自己身上,也确實逐層的點在了直至 window 的每一個元素身上
    • 但是到底是先點在自己身上,還是先點在了 window 身上呢
    • 先點在自己身上,就是先執行自己的事件處理函數,逐層向上最後執行 window 的事件處理函數

      反之,則是先執行 window 的事件處理函數,逐層向下最後執行自己身上的事件處理函數

冒泡、捕獲、目标

  • 我們剛才聊過了,每一個事件,都是有可能從自己到 window ,有可能要執行多個同類型事件
  • 那麼這個執行的順序就有一些說法了

目标

  • 你是點選在哪個元素身上了,那麼這個事件的 目标 就是什麼

冒泡

  • 就是從事件 目标 的事件處理函數開始,依次向外,直到 window 的事件處理函數觸發
  • 也就是從下向上的執行事件處理函數

捕獲

  • 就是從 window 的事件處理函數開始,依次向内,隻要事件 目标 的事件處理函數執行
  • 也就是從上向下的執行事件處理函數

冒泡和捕獲的差別

  • 就是在事件的傳播中,多個同類型事件處理函數的執行順序不同

事件委托

  • 就是把我要做的事情委托給别人來做
  • 因為我們的冒泡機制,點選子元素的時候,也會同步觸發父元素的相同僚件
  • 是以我們就可以把子元素的事件委托給父元素來做

事件觸發

  • 點選子元素的時候,不管子元素有沒有點選事件,隻要父元素有點選事件,那麼就可以出發父元素的點選事件
<body>
  <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
  </ul>
  <script>
  	var oUl = document.querySelector('ul');
	oUL.addEventListener('click',function(e){
	console.log('我是 ul 的點選事件,我被觸發了');
})
  </script>
</body>
           
- 像上面一段代碼,當你點選 ul 的時候肯定會觸發
- 但是當你點選 li 的時候,其實也會觸發
           

target

  • target 這個屬性是事件對象裡面的屬性,表示你點選的目标
  • 當你觸發點選事件的時候,你點選在哪個元素上,target 就是哪個元素
  • 這個 target 也不相容,在 IE 下要使用 srcElement
<body>
  <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
  </ul>
  <script>
  	var oUl = docuemnt.querySelector('ul')
    
    oUl.addEventListener('click', function (e) {
      e = e || window.event
      var target = e.target || e.srcElement
      console.log(target)
    })
  </script>
</body>
           
- 上面的代碼,當你點選 ul 的時候,target 就是 ul
- 當你點選在 li 上面的時候,target 就是 li
           

委托

  • 這個時候,當我們點選 li 的時候,也可以觸發 ul 的點事件
  • 這個時候,當我們點選 li 的時候,也可以觸發 ul 的點事件
  • 這個時候,我們就可以把 li 的事件委托給 ul 來做
<body>
  <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
  </ul>
  <script>
  	var oUl = docuemnt.querySelector('ul')
    
    oUl.addEventListener('click', function (e) {
      e = e || window.event
      var target = e.target || e.srcElement
     
      // 判斷你點選的是 li
      if (target.nodeName.toUpperCase === 'LI') {
      	// 确定點選的是 li
        // 因為當你點選在 ul 上面的時候,nodeName 應該是 'UL'
        // 去做點選 li 的時候該做的事情了
        console.log('我是 li,我被點選了')
      }
    })
  </script>
</body>
           
- 上面的代碼,我們就可以把 li 要做的事情委托給 ul 來做
           

總結

  • 為什麼要用事件委托
    • 我頁面上本身沒有 li
    • 我通過代碼添加了一些 li
    • 添加進來的 li 是沒有點選事件的
    • 我每次動态的操作完 li 以後都要從新給 li 綁定一次點選事件
    • 比較麻煩
    • 這個時候隻要委托給 ul 就可以了
    • 因為新加進來的 li 也是 ul 的子元素,點選的時候也可以觸發 ul 的點選事件
  • 事件委托的書寫
    • 元素的事件隻能委托給結構父級或者再結構父級的同樣的事件上
    • li 的點選事件,就不能委托給 ul 的滑鼠移入事件
    • li 的點選事件,隻能委托給 ul 或者在高父級的點選事件上

預設行為

  • 預設行為,就是不用我們注冊,它自己就存在的事情
    • 比如我們點選滑鼠右鍵的時候,會自動彈出一個菜單
    • 比如我們點選 a 标簽的時候,我們不需要注冊點選事件,他自己就會跳轉頁面
    • 。。。
  • 這些不需要我們注冊就能實作的事情,我們叫做 預設事件

阻止預設行為

  • 有的時候,我們不希望浏覽器執行預設事件
    • 比如我給 a 标簽綁定了一個點選事件,我點選你的時候希望你能告訴我你的位址是什麼
    • 而不是直接跳轉連結
    • 那麼我們就要把 a 标簽原先的預設事件阻止,不讓他執行預設事件
  • 我們有兩個方法來阻止預設事件
    • e.preventDefault()

      : 非 IE 使用
    • e.returnValue = false

      :IE 使用
  • 我們阻止預設事件的時候也要寫一個相容的寫法
<a href="https://www.baidu.com">點選我試試</a>
<script>
	var oA = document.querySelector('a')
  
  a.addEventListener('click', function (e) {
    e = e || window.event
    
    console.log(this.href)
    
    e.preventDefault ? e.preventDefault() : e.returnValue = false
  })
</script>
           
- 這樣寫完以後,你點選 a 标簽的時候,就不會跳轉連結了
- 而是會在控制台列印出 a 标簽的 href 屬性的值