#hello,JS:10 -02事件對(duì)象和事件代理

一、事件的IE兼容性

在老版的IE瀏覽器中,
不支持:addEventListener和removeEventListener 兩種事件綁定的方法
支持(可實(shí)現(xiàn)):attachEvent和detachEvent 兩種方法,同時(shí)接收兩個(gè)相同參數(shù)
a、事件處理程序名稱
b、事件處理程序方法
由于IE支持事件冒泡,所以添加的程序會(huì)被添加到冒泡階段,使用attachEvent可以添加事件處理程序:

<input id="btnClick"  type="button" value="Click Here" />

<script>
   var btnClick = document.getElementById('btnClick')
   var handler = function(){
          alert(this.id)
}
   btnClick.attachEvent('onclick',handler);
</script>
  • attachEvent只能在冒泡階段監(jiān)聽(tīng)事件,只有兩個(gè)參數(shù):(事件類型,事件處理函數(shù))
  • ie中的this:它所得到的并不是當(dāng)前元素,而是window對(duì)象,返回值則為undefined

二、跨瀏覽器的事件處理程序

了解不同的瀏覽器下處理事件處理程序的區(qū)別
在添加事件處理程序事addEventListenerattachEvent主要有幾個(gè)區(qū)別:
1、參數(shù)個(gè)數(shù)不相同,這個(gè)最直觀,addEventListener有三個(gè)參數(shù),attachEvent只有兩個(gè),attachEvent添加的事件處理程序只能發(fā)生在冒泡階段,addEventListener第三個(gè)參數(shù)可以決定添加的事件處理程序是在捕獲階段還是冒泡階段處理(我們一般為了瀏覽器兼容性都設(shè)置為冒泡階段)

2、第一個(gè)參數(shù)意義不同,addEventListener第一個(gè)參數(shù)是事件類型(比如click,load),而attachEvent第一個(gè)參數(shù)指明的是事件處理函數(shù)名稱(onclick,onload)

3、事件處理程序的作用域不相同,addEventListener的作用域是元素本身,this是指的觸發(fā)元素,而attachEvent事件處理程序會(huì)在全局變量?jī)?nèi)運(yùn)行,this是window,所以剛才例子才會(huì)返回undefined,而不是元素id

4、為一個(gè)事件添加多個(gè)事件處理程序時(shí),執(zhí)行順序不同,addEventListener添加會(huì)按照添加順序執(zhí)行,而attachEvent添加多個(gè)事件處理程序時(shí)順序無(wú)規(guī)律(添加的方法少的時(shí)候大多是按添加順序的反順序執(zhí)行的,但是添加的多了就無(wú)規(guī)律了),所以添加多個(gè)的時(shí)候,不依賴執(zhí)行順序的還好,若是依賴于函數(shù)執(zhí)行順序,最好自己處理,不要指望瀏覽器

三、事件對(duì)象

image

如剛才例子http://js.jirengu.com/hahid/1/edit?html,js 中在控制臺(tái)上打印出事件,事件內(nèi)都是一些對(duì)象(帶有屬性和值),可以從這堆屬性中觀察到一些重要的參考(只是部分例舉),如:

altKey:false  //表示在點(diǎn)擊事件的時(shí)候,沒(méi)有點(diǎn)alt鍵
bubbles:true  //表示這個(gè)事件是冒泡
clientX:39
clientY:18   //表示它的一個(gè)位置
toElement:button#btn   //說(shuō)明當(dāng)前傳遞的元素

介紹幾個(gè)常用屬性:

  • stopPropagation()
    如圖:
    [圖片上傳失敗...(image-187d5b-1534131542419)]
    阻止冒泡繼續(xù)?
    在dom事件流中,分別會(huì)在捕獲和冒泡階段都綁定事件,先捕獲后冒泡進(jìn)行輸出。假設(shè)我們現(xiàn)在不管捕獲,只管冒泡,并給body綁定一個(gè)監(jiān)聽(tīng)事件,當(dāng)它聽(tīng)到事件做了一件事:一點(diǎn)stopPropagation()就停止冒泡,即點(diǎn)擊div之后,body監(jiān)聽(tīng)到消息,后面的頁(yè)面元素渲染就不再處理。即將事件冒泡停止,不會(huì)再上傳消息。捕獲也亦然。
  • preventDefault()
    瀏覽器的默認(rèn)事件如何阻止?
    某些元素?fù)碛心J(rèn)事件,為瀏覽器的默認(rèn)行為。如a鏈接點(diǎn)擊時(shí)則會(huì)跳轉(zhuǎn)、如form表單中table=submit,當(dāng)點(diǎn)擊該按鈕時(shí),瀏覽器會(huì)把它所在的form表單做一次提交。假設(shè)想阻止其默認(rèn)行為,則可以通過(guò)綁定事件:preventDefault()阻止其行為。之后再做一些校驗(yàn)或判斷,用JS 做當(dāng)前頁(yè)面跳轉(zhuǎn)。即在跳轉(zhuǎn)這一層級(jí)可以做些事:
    假設(shè)制定一個(gè)域名的a鏈接才能跳轉(zhuǎn)(而頁(yè)面則是用戶可自行寫(xiě)鏈接)先阻止其默認(rèn)時(shí)間,再獲取當(dāng)前herf的值、hostname(域名)

假設(shè)表單提交,用戶校驗(yàn),校驗(yàn)成功之后,就手動(dòng)去做一些跳轉(zhuǎn)

  • e.stopPropagation( ) 取消事件進(jìn)一步捕獲或冒泡
    事件冒泡和事件捕獲的應(yīng)用場(chǎng)景
//選中元素
var container = document.querySelector('.container')

var box = document.querySelector('.box')

var target = document.querySelector('.target')

//綁定事件
container.addEventListener('click', function(e){
  console.log('container 捕獲 click...')
},true)

box.addEventListener('click', function(e){
  console.log('box 捕獲 click...')
},true)

target.addEventListener('click',function(e){
  console.log('target 捕獲 click...')
},true)


container.addEventListener('click', function(e){
  console.log('container 冒泡 click...')
},false)

box.addEventListener('click', function(e){
  e.stopPropagation()
  console.log('box 冒泡 click...')
},false)

target.addEventListener('click',function(e){
  console.log('target 冒泡 click...')
},false)

如圖:


image

多個(gè)阻止函數(shù)來(lái)阻止冒泡事件


image
  • e.preventDefault( ) 阻止事件默認(rèn)行為
    鏈接:阻止事件默認(rèn)行為
    剛開(kāi)始是這樣的:沒(méi)有跳轉(zhuǎn),只有一直輸出:
    image

代碼:

<!DOCTYPE html>
<html>
    <head>
       <meta charset="utf-8">
      <title>阻止默認(rèn)事件</title>
    </head>
       <body>
          <a >baidu</a>
        </body>
   </html>

<script>
    document.querySelector('a').onclick = function(e){
           e.preventDefault()
           console.log(this.href)
}
</script>

接著看圖所示,添加一個(gè)if判斷,再點(diǎn)擊baidu鏈接,控制臺(tái)只輸出一次地址,頁(yè)面則出現(xiàn)百度的網(wǎng)頁(yè):


image

代碼:

//html同上

<script>
document.querySelector('a').onclick = function(e){
  e.preventDefault()
  console.log(this.href)
  if(/baidu.com/.test(this.href)){
    location.href = this.href
  }
}//函數(shù)表示:如果這個(gè)鏈接是baidu.com,那就跳轉(zhuǎn)
</script>

假如html代碼中

 <a >baidu</a>

改為:

 <a >baidu</a>

最后頁(yè)面和控制臺(tái)都不會(huì)有任何反應(yīng)。而這就是e.preventDefault( ) 阻止事件默認(rèn)行為

四、常用HTML事件及演示

例子鏈接:常見(jiàn)事件使用演示

五、事件代理

鏈接:事件代理的一些嘗試
首先,我們?yōu)閮蓚€(gè)box綁定兩個(gè)事件,先綁定box1,如圖:

image

通過(guò)選擇參數(shù)$('.box')作為box1的當(dāng)前元素,所以再去綁定事件之后,則只會(huì)出現(xiàn)第一個(gè)box1文本內(nèi)容。
但是,我們嘗試地使用函數(shù)$$(selector)綁定兩個(gè)元素的事件,再點(diǎn)擊box1和box2沒(méi)有任何輸出,如圖:
image

通過(guò)頁(yè)面控制臺(tái)檢驗(yàn):

$$('.box')
 -->  NodeList(2) [div.box, div.box]//1、確實(shí)出現(xiàn)了所選的兩個(gè)元素,但是要確認(rèn)有沒(méi)有onclick
      0: div.box
      1: div.box
      length: 2
      __proto__: NodeList   //3、我們所看到NodeList,是一個(gè)類數(shù)組對(duì)象,里面的屬性值并沒(méi)有onclick和addEventListener
$$('.box').onclick   //2、于是測(cè)試之后undefined,即綁定事件只能針對(duì)單個(gè)去綁定事件
 -->  undefined
image

那如何解決兩個(gè)元素同時(shí)綁定事件呢?還是從控制臺(tái)nodelist的對(duì)象中尋找可用的參數(shù)去解決,即有forEach遍歷兩個(gè)元素,實(shí)現(xiàn)兩個(gè)都綁定了事件,即:

//html同上

<script>
function $$(selector){
  return document.querySelectorAll(selector)
}
$$('.box').forEach(function(node){
  node.onclick = function(){
     console.log(this.innerText)
  }
})
</script>

圖:


image

那么,我們有沒(méi)有更簡(jiǎn)單的方法實(shí)現(xiàn)當(dāng)前所有元素都綁定了事件?看html即可以知道,我們可以直接綁定父元素container,即

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
     <div class="container">
     <div class="box">box1</div>
     <div class="box">box2</div>
     <div class="hello">hello</div>
   </div>
  
</body>
</html>

<script>
function $(selector){
  return document.querySelector(selector)
}
function $$(selector){
  return document.querySelectorAll(selector)
}
$('.container').onclick = function(e){
  if(e.target.classList.contains('box')){
    console.log(e.target.innerText)
  }
}//表示:如果我點(diǎn)擊了一個(gè)元素(e.target),它的classList包含了'box',
//那么它就輸出這個(gè)元素的文本內(nèi)容。具有語(yǔ)義化
</script>

再想到更多的場(chǎng)景,如有一個(gè)按鈕,如何綁定這個(gè)按鈕實(shí)現(xiàn)這樣一個(gè)需求:當(dāng)點(diǎn)擊這個(gè)按鈕的時(shí)候,則會(huì)在父元素下再添加一個(gè)box。這個(gè)如何實(shí)現(xiàn)?如圖:


image

代碼如下:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
     <div class="container">
     <div class="box">box1</div>
     <div class="box">box2</div>
     <div class="box">box3</div>
     <div class="hello">hello</div>
   </div>
  <button id="add">add</button>
  <!--需求:當(dāng)點(diǎn)擊這個(gè)按鈕的時(shí)候,則會(huì)在父元素下再添加一個(gè)box-->
</body>
</html>


<script>
function $(selector){
  return document.querySelector(selector)
}

function $$(selector){
  return document.querySelectorAll(selector)
}

$('.container').onclick = function(e){
  if(e.target.classList.contains('box')){
    console.log(e.target.innerText)
 }
}//事件代理的核心所在

//表示:如果我點(diǎn)擊了一個(gè)元素(e.target),它的classList包含了'box',那么它就輸出這個(gè)元素的文本內(nèi)容。具有語(yǔ)義化


var i=4  //這是因?yàn)橹坝衎ox3了
$('#add').onclick = function(){
  var box = document.createElement('div')//創(chuàng)建一個(gè)box元素
  box.classList.add('box')//創(chuàng)建的當(dāng)前元素去添加一個(gè)class叫做box
  box.innerText ='box' + (i++)//表示每點(diǎn)擊一次i就增加一個(gè)
  $('.container').appendChild(box)//最后將box這個(gè)元素添加進(jìn).container里面
}
</script>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • ??JavaScript 與 HTML 之間的交互是通過(guò)事件實(shí)現(xiàn)的。 ??事件,就是文檔或?yàn)g覽器窗口中發(fā)生的一些特...
    霜天曉閱讀 3,682評(píng)論 1 11
  • JavaScript 程序采用了異步事件驅(qū)動(dòng)編程模型。在這種程序設(shè)計(jì)風(fēng)格下,當(dāng)文檔、瀏覽器、元素或與之相關(guān)的對(duì)象發(fā)...
    劼哥stone閱讀 1,330評(píng)論 3 11
  • 聲明:本文來(lái)源于http://www.webzsky.com/?p=731我只是在這里作為自己的學(xué)習(xí)筆記整理一下(...
    angryyan閱讀 7,239評(píng)論 1 6
  • 以下文章為轉(zhuǎn)載,對(duì)理解JavaScript中的事件處理機(jī)制很有幫助,淺顯易懂,特分享于此。 什么是事件? 事件(E...
    jxyjxy閱讀 3,163評(píng)論 1 10
  • JavaScript 與 HTML 之間的交互是通過(guò)事件實(shí)現(xiàn)的。事件,就是文檔或?yàn)g覽器窗口中發(fā)生的一些特定的交互瞬...
    threetowns閱讀 409評(píng)論 0 0

友情鏈接更多精彩內(nèi)容