專題復(fù)習(xí)五、DOM API及事件監(jiān)聽

放自己用DOM寫的作品鏈接
寫于2017.08.07
一、關(guān)于DOM

  • 什么是DOM
    DOM是JavaScript操作網(wǎng)頁的接口,全稱為“文檔對象模型”(Document Object Model)。它的作用是將網(wǎng)頁轉(zhuǎn)為一個JavaScript對象,從而可以用腳本進(jìn)行各種操作(比如增刪內(nèi)容)。
    瀏覽器會根據(jù)DOM模型,將結(jié)構(gòu)化文檔(比如HTML和XML)解析成一系列的節(jié)點,再由這些節(jié)點組成一個樹狀結(jié)構(gòu)(DOM Tree)。所有的節(jié)點和最終的樹狀結(jié)構(gòu),都有規(guī)范的對外接口。所以,DOM可以理解成網(wǎng)頁的編程接口。
    嚴(yán)格地說,DOM不屬于JavaScript,但是操作DOM是JavaScript最常見的任務(wù),而JavaScript也是最常用于DOM操作的語言
  • DOM的節(jié)點
    DOM的最小組成單位叫做節(jié)點(node)。文檔的樹形結(jié)構(gòu)(DOM樹),就是由各種不同類型的節(jié)點組成。每個節(jié)點可以看作是文檔樹的一片葉子。
    節(jié)點的類型有七種。
    *Document:整個文檔樹的頂層節(jié)點
    *DocumentType:doctype標(biāo)簽(比如<!DOCTYPE html>)
    *Element:網(wǎng)頁的各種HTML標(biāo)簽(比如<body>、<a>等)
    *Attribute:網(wǎng)頁元素的屬性(比如class="right")
    *Text:標(biāo)簽之間或標(biāo)簽包含的文本
    *Comment:注釋
    *DocumentFragment:文檔的片段
    DOM樹如下圖:

image.png

具體DOM學(xué)習(xí)建議參考鏈接:http://javascript.ruanyifeng.com/#dom
二、事件模型

  • 什么是事件
    事件是一種異步編程的實現(xiàn)方式,本質(zhì)上是程序各個組成部分之間的通信。一般來講,有一下特點:
    1、某某訂閱了/關(guān)注/監(jiān)聽了×××
    2、×××發(fā)生變化
    3、某某得到通知
    體現(xiàn)在DOM機(jī)制里就是:用戶的操作發(fā)生變化,代碼得到通知

  • 事件EventTarget接口
    DOM的事件操作(監(jiān)聽和觸發(fā)),都定義在EventTarget接口。Element節(jié)點、document節(jié)點和window對象,都部署了這個接口。此外,XMLHttpRequest、AudioNode、AudioContext等瀏覽器內(nèi)置對象,也部署了這個接口。
    該接口就是3個方法:
    1、addEventListener:綁定事件的監(jiān)聽函數(shù)
    例:
    target.addEventListener(type, listener[, useCapture]);
    type:事件名稱,大小寫敏感。
    listener:監(jiān)聽函數(shù)。事件發(fā)生時,會調(diào)用該監(jiān)聽函數(shù)。
    useCapture:布爾值,默認(rèn)為false(監(jiān)聽函數(shù)只在冒泡階段被觸發(fā))。true是在捕獲階段觸發(fā)
    addEventListener方法可以為當(dāng)前對象的同一個事件,添加多個監(jiān)聽函數(shù)。這些函數(shù)按照添加順序觸發(fā),即先添加先觸發(fā)。如果為同一個事件多次添加同一個監(jiān)聽函數(shù),該函數(shù)只會執(zhí)行一次,多余的添加將自動被去除(不必使用removeEventListener方法手動去除)。
    2、removeEventListener:移除事件的監(jiān)聽函數(shù)
    例:
    div.addEventListener('click', listener, false);
    removeEventListener方法移除的監(jiān)聽函數(shù),必須與對應(yīng)的addEventListener方法的參數(shù)完全一致,而且必須在同一個元素節(jié)點,否則無效。
    3、dispatchEvent:觸發(fā)事件
    dispatchEvent方法在當(dāng)前節(jié)點上觸發(fā)指定事件,從而觸發(fā)監(jiān)聽函數(shù)的執(zhí)行。該方法返回一個布爾值,只要有一個監(jiān)聽函數(shù)調(diào)用了Event.preventDefault(),則返回值為false,否則為true
    例:
    para.addEventListener('click', hello, false);
    var event = new Event('click');
    para.dispatchEvent(event);
    上面代碼在當(dāng)前節(jié)點觸發(fā)了click事件

  • 3種綁定監(jiān)聽函數(shù)的方法
    1、HTML標(biāo)簽的on-屬性
    例:元素標(biāo)簽的屬性中,直接定義某些事件的監(jiān)聽代碼
    <body onload="doSomething()">
    <div onclick="console.log('觸發(fā)事件')">
    上面代碼為body節(jié)點的load事件、div節(jié)點的click事件,指定了監(jiān)聽函數(shù)。
    使用這個方法指定的監(jiān)聽函數(shù),只會在冒泡階段觸發(fā)

    另外,Element元素節(jié)點的setAttribute方法,其實設(shè)置的也是這種效果。
    el.setAttribute('onclick', 'doSomething()');
    2、Element節(jié)點的事件屬性
    Element節(jié)點對象有事件屬性,同樣可以指定監(jiān)聽函數(shù)。
    例:
    window.onload = doSomething;
    div.onclick = function(event){
    console.log('觸發(fā)事件');
    };
    使用這個方法指定的監(jiān)聽函數(shù),只會在冒泡階段觸發(fā)。
    3、addEventListener方法
    window.addEventListener('load', doSomething, false);(詳解如上)
    總結(jié):第一種“HTML標(biāo)簽的on-屬性”,違反了HTML與JavaScript代碼相分離的原則;第二種“Element節(jié)點的事件屬性”的缺點是,同一個事件只能定義一個監(jiān)聽函數(shù),也就是說,如果定義兩次onclick屬性,后一次定義會覆蓋前一次。

  • 事件的捕獲與冒泡階段
    1、操作系統(tǒng)最先知道用戶點擊了鼠標(biāo),瀏覽器次之
    2、child被點擊了,意味著parent也被點擊了
    3、那么如果同時監(jiān)聽了child和parent,誰先通知我
    例子:如果對parent和child同時設(shè)置了監(jiān)聽,那么當(dāng)我點擊child,誰先通知我
    捕獲階段:parent先通知,child后通知(一般不用)
    冒泡階段:child先通知,parent后通知

  • e.target與e.currentTarget
    e.target代表你點擊的那個元素,而e.currentTarget代表你監(jiān)聽的那個元素,如果你處于捕獲或者冒泡階段,二者是不一樣的

  • 阻止默認(rèn)事件
    document.querySelector("a").addEventListener('click',function(e){
    e.preventDefault()
    })
    這樣的話a就不會跳轉(zhuǎn)了。如果在父元素阻止默認(rèn)事件,那a也不跳轉(zhuǎn)了,所以一般不建議這樣做

  • 停止冒泡
    e.stopPropagation( )(在子元素加入,則不通知爸爸了,不會再向上傳播)

  • 事件委托
    由于事件會在冒泡階段向上傳播到父節(jié)點,因此可以把子節(jié)點的監(jiān)聽函數(shù)定義在父節(jié)點上,由父節(jié)點的監(jiān)聽函數(shù)統(tǒng)一處理多個子元素的事件。這種方法叫做事件委托
    例:
    HTML代碼:
    <ul>
    <li>選項1</li>
    <li>選項2</li>
    <li>選項3</li>
    <li>選項4</li>
    </ul>
    JS代碼:
    var ul =document.querySelector('ul')
    function fn(e){
    if(e.target.tagName ==="LI"){
    console.log("ok")(如果li里面裹一層span,點擊span就不能執(zhí)行監(jiān)聽函數(shù))
    }
    }
    ul.addEventListener('click',fn)
    優(yōu)化執(zhí)行函數(shù):
    function fn(e){
    var el = e.target
    while(el.tagName !=="LI"){
    el =el.parentNode(向上遍歷父元素)
    }
    if(el){
    console.log('yes')
    }
    }
    但是實際上我只需要遍歷到我監(jiān)聽的元素就可以了,如果直到遍歷到監(jiān)聽的元素還沒有的話,就認(rèn)為沒有了
    例:
    HTML代碼:
    <div>
    <p>我是<span>p</span></p>
    <hi>我是<span>h1</span></hi>
    </div>
    JS代碼:
    var div =document.querySelector('div')
    function fn(e){
    var el = e.target
    while(el.tagName !=="H1"){
    el =el.parentNode(向上遍歷父元素)
    if(el===div){
    el=null
    break;
    }
    }
    if(el){
    console.log('yes')
    }
    }
    div.addEventListener('click',fn(e))

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • 事件是一種異步編程的實現(xiàn)方式,本質(zhì)上是程序各個組成部分之間的通信。DOM支持大量的事件,本節(jié)介紹DOM的事件編程。...
    周花花啊閱讀 678評論 0 3
  • 題目1: DOM0 事件和DOM2級在事件監(jiān)聽使用方式上有什么區(qū)別? Dom0級Dom0級事件處理程序是將一個函數(shù)...
    QQQQQCY閱讀 391評論 0 0
  • 問答 一、dom對象的innerText和innerHTML有什么區(qū)別? innerTextinnerText是一...
    婷樓沐熙閱讀 471評論 0 0
  • 導(dǎo)讀:本文是teren對DOM事件知識點所做的進(jìn)一步整理,整理資料主要參考DOM事件簡介和饑人谷課件,如果對DOM...
    犯迷糊的小羊閱讀 4,154評論 1 5
  • 中廳花正怒,香滿院,游人不歸蝶常舞,誰解其中味?黃花斗霜綴清秋,敢與時令爭!花如此,我輩豈能屈?高朋滿座,美酒佳肴...
    你就是我心中的棉花糖閱讀 200評論 1 0

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