如何造成一個完整的HTML對象

寫在前面,本文將同步發佈於Blog、掘金、segmentfault、知乎等處,若是本文對你有幫助,記得爲我獲得個人我的技術博客項目給個star哦。html

爲什麼寫這篇文章?

你可能作Web開發已經有一段時間,你是否有想過下列問題呢?
爲何div元素甚至是全部的html元素均可以使用addEventListener來添加事件呢?
爲何每一個DOM節點都有parentNode、firstChild、nodeType等屬性呢?
爲何每一個DOM元素都有className、classList、innerHTML等屬性呢?
爲何有些DOM元素有accessKey、contentEditable、isContentEditable等屬性呢?
爲何每一個DOM元素都有onclick、ondblclick、ondrag等屬性?
本文就是來解答這些簡單而又不「簡單」的問題。node

EventTarget

定義

EventTarget 是一個由能夠接收事件的對象實現的接口,而且能夠爲它們建立偵聽器。git

做用

Element,document 和 window 是最多見的事件目標,可是其餘對象也能夠是事件目標,好比XMLHttpRequest,AudioNode,AudioContext 等等。
許多事件目標(包括元素,文檔和 window)還支持經過 onXXX(如onclick) 屬性和屬性設置事件處理程序。github

該接口的方法

EventTarget.addEventListener()

在EventTarget上註冊特定事件類型的事件處理程序。web

EventTarget.removeEventListener()

EventTarget中刪除事件偵聽器。segmentfault

EventTarget.dispatchEvent()

將事件分派到此EventTarget。app

咱們本身實現EventTarget

var EventTarget = function() {
  this.listeners = {};
};

EventTarget.prototype.listeners = null;
EventTarget.prototype.addEventListener = function(type, callback) {
  if (!(type in this.listeners)) {
    this.listeners[type] = [];
  }
  this.listeners[type].push(callback);
};

EventTarget.prototype.removeEventListener = function(type, callback) {
  if (!(type in this.listeners)) {
    return;
  }
  var stack = this.listeners[type];
  for (var i = 0, l = stack.length; i < l; i++) {
    if (stack[i] === callback){
      stack.splice(i, 1);
      return;
    }
  }
};

EventTarget.prototype.dispatchEvent = function(event) {
  if (!(event.type in this.listeners)) {
    return true;
  }
  var stack = this.listeners[event.type].slice();

  for (var i = 0, l = stack.length; i < l; i++) {
    stack[i].call(this, event);
  }
  return !event.defaultPrevented;
};

Node

定義

Node是一個接口,許多DOM類型從這個接口繼承,並容許相似地處理(或測試)這些各類類型。Node是一個接口,許多DOM類型從這個接口繼承,並容許相似地處理(或測試)這些各類類型。佈局

有那些接口重Node繼承其方法和屬性?

Document, Element, CharacterData (which Text, Comment, and CDATASection inherit), ProcessingInstruction, DocumentFragment, DocumentType, Notation, Entity, EntityReference
PS:在方法和屬性不相關的特定狀況下,這些接口可能返回null。它們可能會拋出異常 - 例如,當將子節點添加到不容許子節點存在的節點時。測試

接口相關的屬性和方法

屬性

Node.baseURI

返回一個表示base URL的DOMString。不一樣語言中的base URL的概念都不同。 在HTML中,base URL表示協議和域名,以及一直到最後一個'/'以前的文件目錄。this

Node.childNodes

返回一個包含了該節點全部子節點的實時的NodeList。NodeList 是「實時的」意思是,若是該節點的子節點發生了變化,NodeList對象就會自動更新。

Node.firstChild

返回該節點的第一個子節點,若是該節點沒有子節點則返回null。

Node.lastChild

返回該節點的最後一個子節點,若是該節點沒有子節點則返回null。
此處省略若干Node接口屬性,更多屬性查看這裏

方法

--------------------重點分割線-------------------
重點:從其父類EventTarget繼承了addEventListener、removeEventListener、dispatchEvent等方法。

Node.appendChild()

將一個節點添加到指定父節點的子節點列表末尾。

Node.contains()

返回的是一個布爾值,來表示傳入的節點是否爲該節點的後代節點。

Node.cloneNode()

返回調用該方法的節點的一個副本。
此處省略若干Node接口方法,更多方法查看這裏

Element

說明

Element是很是通用的基類,全部 Document對象下的對象都繼承它。這個接口描述了全部相同種類的元素所廣泛具備的方法和屬性。 這些繼承自Element而且增長了一些額外功能的接口描述了具體的行爲。
PS:HTMLElement 接口是全部HTML元素的基礎接口, 而 SVGElement 接口是全部SVG元素的基本接口。
在web之外的語言,像 XUL 能夠經過 XULElement 的API,也能實現它。

屬性

全部屬性繼承至它的祖先接口 Node, 和它所擴展的接口 EventTarget, 而且從如下部分繼承了屬性ParentNode, ChildNode, NonDocumentTypeChildNode, 和Animatable.

Element.assignedSlot

返回元素對應的 HTMLSlotElement 接口

Element.attributes

返回一個與該元素相關的全部屬性集合NamedNodeMap

Element.classList

返回該元素包含的class屬性是一個DOMTokenList.

Element.className

它是一個 DOMString 表示這個元素的class.
此處省略若干Element接口屬性,更多方法查看這裏

方法

--------------------重點分割線-------------------
從它的父類(Node)和它父類的父類(EventTarget)繼承方法,並實現parentNode、ChildNode、NonDocumentTypeChildNode、Animatable。
此處省略若干Element接口方法,更多方法查看這裏

Element.closest()

方法用來獲取匹配特定選擇器且離當前元素最近的祖先元素(也能夠是當前元素自己)。若是匹配不到,則返回 null。

Element.getAttribute()

返回元素上一個指定的屬性值。若是指定的屬性不存在,則返回 null 或 "" (空字符串)。

Element.getElementsByClassName()

參數中給出類的列表,返回一個動態的 HTMLCollection ,這裏麪包含了全部持有這些類的後代元素。
此處省略若干Element接口方法,更多方法查看這裏

HTMLElement

做用

HTMLElement 接口表示全部的 HTML 元素。一些HTML元素直接實現了HTMLElement接口,其它的間接實現HTMLElement接口。

屬性

--------------------重點分割線-------------------
繼承自父接口Element和 GlobalEventHandlers的屬性。
HTMLElement.accessKey DOMString 獲取/設置元素訪問的快捷鍵
HTMLElement.accessKeyLabel DOMString 返回一個包含元素訪問的快捷鍵的字符串(只讀)
HTMLElement.contentEditable DOMString 獲取/設置元素的可編輯狀態
HTMLElement.isContentEditable Boolean 代表元素的內容是否可編輯(只讀)
此處省略若干HTMLElement接口屬性,更多方法查看這裏

Event handlers

HTMLElement.onTouchStart
HTMLElement.onTouchEnd
HTMLElement.onTouchMove
HTMLElement.onTouchEnter
HTMLElement.onTouchLeave
HTMLElement.onTouchCancel

方法

HTMLElement.blur() void 元素失去焦點
HTMLElement.click() void 觸發元素的點擊事件
HTMLElement.focus() void 元素得到焦點
HTMLElement.forceSpellCheck() void

GlobalEventHandlers

定義

GlobalEventHandlers接口描述了事件處理程序像HTMLElement常見的幾個接口,文件,窗口,或WorkerGlobalScope Web Workers。這些接口能夠實現更多的事件處理程序。

屬性

GlobalEventHandlers.onabort

中斷事件。

GlobalEventHandlers.onblur

失去焦點事件。

GlobalEventHandlers.onfocus

獲取焦點事件。
此處省略若干GlobalEventHandlers接口屬性,更多方法查看這裏

元素接口

該接口用於建立對應的元素。
如:
HTMLDivElement 接口提供了一些特殊屬性(它也繼承了一般的 HTMLElement 接口)來操做div元素。
HTMLFormElement接口能夠建立或者修改<form>對象;它繼承了HTMLElement接口的方法和屬性。
HTMLAnchorElement 接口表示超連接元素,並提供一些特別的屬性和方法(除了那些繼承自普通 HTMLElement對象接口的以外)以用於操做這些元素的佈局和顯示。
......

回答前面問題

經過上面的知識,咱們瞭解到:
HTMLDivElement(其餘元素接口) 繼承 HTMLElement 和 GlobalEventHandlers 接口。
HTMLElement 繼承 Element 接口。
Element 繼承 Node 接口。
Node 繼承 EventTarget 接口。
html由來
爲何div元素甚至是全部的html元素均可以使用addEventListener來添加事件呢?
回答:從 EventTarget 接口中繼承而來。
爲何每一個DOM節點都有parentNode、firstChild、nodeType等屬性呢?
回答:從 Node 接口中繼承而來。
爲何每一個DOM元素都有className、classList、innerHTML等屬性呢?
回答:從 Element 接口中繼承而來。
爲何有些DOM元素有accessKey、contentEditable、isContentEditable等屬性呢?
回答:從 HTMLElement 接口中繼承而來。
爲何每一個DOM元素都有onclick、ondblclick、ondrag等屬性?
回答:從 GlobalEventHandlers 接口中繼承而來。
--------------------重點分割線-------------------

只有經過上面的繼承關係,咱們獲得的 DOM 元素纔是一個完整的 HTML 對象,咱們才能爲它設置/獲取屬性、綁定事件、添加樣式類等操做。

參考文檔:

EventTarget
Node
Element
HTMLElement
GlobalEventHandlers
相關文章
相關標籤/搜索