整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          快速了解JavaScript的DOM模型

          快速了解JavaScript的DOM模型

          DOM全稱Document Object Model,即文檔對象模型。是HTML和XML文檔的編程接口,DOM將文檔(HTML或XML)描繪成一個多節點構成的結構。使用JavaScript可以改變文檔的結構、樣式和內容。

          W3C DOM由以下三部分組成:

          • 核心DOM - 針對任何結構化文檔的標準模型。
          • XML DOM - 針對XML文檔的標準模型。
          • HTML DOM - 針對HTML文檔的標準模型。

          分類

          DOM目前有三種級別:

          • DOM Level 1:1998年10月成為W3C的推薦標準,主要定義HTML和XML文檔的底層結構。
          • DOM Level 2: 在DOM1基礎上擴充了方法和屬性,引入了與文檔更多的交互能力。主要包括DOM視圖、DOM樣式、DOM事件、DOM遍歷和范圍等。
          • DOM Level 3:引入了將XML文檔加載和序列化的方法。提供了驗證文檔有效性的能力。

          節點樹

          以下面的HTML為例:

          <html>
          <head>
              <meta charset="UTF-8">
              <title>節點樹</title>
          </head>
          <body>
              <div>測試塊</div>
              <a href="/about">鏈接</a>
          </body>
          </html>

          瀏覽器會將HTML文檔解析成節點并組成節點樹。

          HTML DOM中通過不同類型節點來表示, Document是每個文檔的根節點。這里的document只有一個<html>子節點,稱之為文檔元素(Element)。Element表示元素類型的節點,Text表示文本類型的節點。

          節點類型

          DOM 的最小組成單位叫做節點(node)。上面的節點樹中,每一段都由不同類型的節點組成。節點的類型有如下幾種:

          • Node:瀏覽器提供的原生節點,下面的節點都繼承它。
          • Document:整個文檔樹的頂層節點
          • DocumentTypedoctype標簽(比如<!DOCTYPE html>)。
          • Element:網頁的各種HTML標簽(比如<body><a>等)。
          • Attr:網頁元素的屬性(比如class="right")。
          • Text:標簽之間或標簽包含的文本。
          • Comment:注釋。
          • CDATASectionCDATA區域,與Comment類型類似。
          • DocumentFragment:文檔的片段。

          Node

          DOM1中定義了一個Node接口,JavaScript中所有節點類型都繼承自Node類型,因此屬性和方法都相同。

          Node類型中定義了nodeType屬性來表明節點的類型,由12個常量表示。任何節點必居其一:

          • Node.ELEMENT_NODE:數值1,對應元素節點Element
          • Node.ATTRIBUTE_NODE:數值2,對應屬性節點Attr
          • Node.TEXT_NODE:數值3,對應文本節點Text
          • Node.CDATA_SECTION_NODE:數值4,對應文檔中CDATA部(不會由解析器解析的文本)。
          • Node.ENTITY_REFERENCE_NODE:數值5,對應實體引用。
          • Node.ENTITY_NODE:數值6,對應實體類型Entity
          • Node.PROCESSING_INSTRUCTION_NODE:數值7,對應處理指令。
          • Node.COMMENT_NODE:數值8,對應注釋節點Comment
          • Node.DOCUMENT_NODE:數值9,對應文檔節點Document
          • Node.DOCUMENT_TYPE_NODE:數值10,對應文檔類型節點DocumentType
          • Node.DOCUMENT_FRAGMENT_NODE:數值11,對應文檔片段節點DocumentFragment
          • Node.NOTATION_NODE:數值12,對應DTD中聲明的符號。

          使用nodeType可以很容易確定節點類型,IE中沒有公開Node類型的構造函數,使用Node.ELEMENT_NODE比較會導致錯誤。為了兼容IE,可以使用數值進行比較:

          if (onenode.nodeType==Node.ELEMENT_NODE) {    // 在IE中無效
              console.log("The Node is an Element.");
          }
          // 或者
          if (oneNode.nodeType==1) {    // 適用所有瀏覽器
              console.log("The Node is an Element.");
          }

          nodeName返回節點的標簽名

          var div=document.getElementByTagName('div')[0];
          console.log(onenode.nodeName);    // DIV

          nodeValue返回字符串,表示節點的文本值,可讀寫。

          var div=document.getElementByTagName('div')[0];
          console.log(onenode.nodeValue);    // null

          節點關系

          文檔中節點都存在著一定的關系,節點之間的關系可以使用類似人類家族關系的形式描述。如,在HTML文檔中,可以把<html>看作是<body>的父元素;相對的,<body>也就是<html>的子元素;而作為<body>同級的<head>兩者之間的關系為兄弟(姐妹)關系。

          Node中提供了幾種節點遍歷的屬性:parentNodechildNodesfirstNode/lastNodepreviousSibling/nextSiblingownerDocument

          Document

          JavaScript通過Document類型表示文檔。瀏覽器中的document對象是HTMLDocument的一個實例,表示整個HTML頁面。Document節點具有以下特征:

          • nodeTypeNode.DOCUMENT_NODE,值為9。
          • nodeName的值為#document
          • nodeValue的值為null
          • parentNode的值為null
          • ownerDocument的值為null
          • 其子結點可能是一個DocumentTypeElementProcessingInstructionComment

          document對象還有一些屬性來表示網頁的一些信息:

          • title:取得當前頁面的標題,也可以修改當前頁面的標題并反映在瀏覽器的標題欄中。但不會改變<title>元素。
          • URL:包含頁面完整的URL
          • domain:只包含頁面的域名。
          • referrer:保存著鏈接到當前頁面的那個頁面的URL。沒有來源頁面的情況下,可能包含空字符串。

          URLdomain屬性是相互關聯的。

          Element

          Element類型用于表現XML或HTML元素,提供對元素標簽名、子節點及特性的訪問。例如<body><div>等。Element節點具有以下特征:

          • nodeTypeNode.ELEMENT_NODE,值為1。
          • nodeName的值為元素的標簽名。
          • nodeValue的值為null
          • parentNode可能是DocumentElement
          • 其子節點可能是ElementTextCommentProcessingInstructionCDATASectionEntityReference

          要訪問元素的標簽名,可以使用nodeName屬性,也可以使用tagName屬性;這兩個屬性會返回相同值。

          獲取<div id="divId"></div>的標簽名:

          var div=document.getElementById("divId");
          console.log(div.tagName);    // DIV
          console.log(div.tagName==div.nodeName);    // true

          特性和屬性

          所有HTML元素都由HTMLElement類型表示,不能直接通過這個類型,也是通過它的子類型來表示。HTMLElement類型直接繼承自Element并添加了一些屬性。每個HTML元素中的特性(例如<div id="d1" title="附加信息" lang="en" class="container">中的idclass等)會自動變成DOM對象的屬性(class特性與className屬性對應)。這些都可以通過div.id等獲取并賦值。

          一個元素中的id等是標準的特性,但也有非標準的特性不能使用div.id方式獲取。那么要用什么方法來訪問非特性。

          DOM主要提供了幾個方法用于對任何特性進行操作,分別是:

          • hasAttribute(qualifiedName: string),檢查qualifiedName這個特性是否存在。
          • getAttribute(qualifiedName: string),獲取qualifiedName這個特性值,如果不存在,則返回null
          • setAttribute(qualifiedName: string, value: string),設置qualifiedName這個特性的值為value。設置的特性名會被同意轉換為小寫形式。
          • removeAttribute(qualifiedName: string),移除qualifiedName這個特性。
          <div id="d1" title="附加信息" lang="en" class="container main" plug-add="添加的非標準的特性">

          以上面的HTML為例,使用這幾種方法。

          var div=document.getElementById('d1');
          div.getAttribute('title');    // 附加信息
          div.hasAttribute('plug-add'); // true
          div.setAttribute('title', '修改附加信息');
          div.removeAttribute('plug-add');

          有兩類特殊的特性,雖有對應的屬性名,但屬性的值與getAttribute()返回的值并不相同。

          第一類特性就是style,用于通過CSS為元素指定樣式。通過getAttribute()返回的style中包含的是CSS文本,而通過屬性返回的是一個對象。

          第二類特性是onclick這樣的事件處理。如果通過getAttribute()返回的是相應代碼的字符串。而訪問onclick屬性返回的是JavaScript函數(如果未指定相應特性,返回的是null)。

          attributes屬性

          Element類型的attributes屬性返回該元素所有屬性節點的一個集合,該集合是一個"動態"的NamedNodeMap對象。NamedNodeMap對象擁有下列方法。

          • getNamedItem(name):返回nodeName屬性等于name的節點。
          • removeNamedItem(name):從列表中移除nodeName屬性等于name的節點。
          • setNamedItem(node):向列表中添加節點,以節點的nodeName屬性為索引。
          • item(pos):返回位于數字pos位置處的節點。

          attributes屬性包含一系列節點,在節點中節點名稱-nodeName 節點值-nodeValue

          var id=element.attributes.getNamedItem('id').nodeValue;
          // 方括號語法
          var id=element.attributes['id'].nodeValue;
          // 屬性名引用
          var id=element.attributes.id;
          // 如果知道特性名所在的下標,也可以使用下標引用,假設id特性名所在下標為0.
          var id=element.attributes[0];

          removeNamedItem()方法與removeAttribute()方法都是將給定名稱的特性刪除,唯一區別就是removeAttribute()沒有返回值,removeNamedItem()返回被刪除特性的Attr節點。

          var oldAttr=element.attributes.removeNamedItem('id');

          setNamedItem()方法為Element添加一個新特性:

          element.attributes.setNamedItem(newAttr);

          一般情況下getAttribute()removeAttribute()setAttribute()方法就夠使用了,但想要遍歷元素的特性,attributes屬性倒是比較方便。下面展示如果迭代元素中每一個特性并將它們以name="value" name="value"這樣的字符串格式。

          function listAttributes(element) {
              var pairs=new Array(),
                  attrName,
                  attrValue,
                  i,
                  len;
              if (element.hasAttributes()) {
                  var attrs=element.attributes;
                  for (i=0, len=element.attributes.length; i < len; i++) {
                      attrName=attrs[i].nodeName;
                      attrValue=attrs[i].nodeValue;
                      pairs.push(attrName + "=\"" + attrValue + "\"");
                  }
              }
              return pairs.join(" ");
          }

          classList

          className屬性用于操作類名,但className是一個字符串,修改后要設置整個字符串的值。

          HTML5擴展了classList屬性實現類名的操作。該屬性返回DOMTokenList集合。定義了幾個方法:

          • add(value):添加字符串到列表中。如果存在就不添加。
          • contains(value):指定值是否存在于列表中,存在則為true,否則為false
          • remove(value):從列表中刪除指定值。
          • toggle(value):列表中存在指定值,刪除它;沒有給定值,添加它。

          Attr

          Attr類型在DOM表示元素特性。特性是位于元素attributes屬性中的節點。具有下列特征:

          • nodeTypeNode.TEXT_NODE,值為3。
          • nodeName的值是特性的名稱。
          • nodeValue的值是特性的名稱。
          • parentNode的值為null
          • 在HTML中不支持子節點(沒有子節點)。
          • 在XML中子節點可以是TextEntityReference

          特性節點不被認為是DOM文檔樹的一部分。最常使用getAttrubute()setAttribute()removeAttribute()方法,很少直接引用特性節點。

          Attr對象有3個屬性:

          • name,特性名稱,與nodeName的值相同。
          • value,特性值,與nodeValue的值相同。
          • specified,布爾值,用于區分特性在代碼中是指定的還是默認的。

          如果要為元素添加特性,可以使用document.createAttribute(localName)方法,創建名為localName的特性節點。例如,要為元素添加align特性,可以使用下列代碼:

          var attr=document.createAttribute("align");
          attr.value="left";
          element.setAttributeNode(attr);
          alert(element.attributes["align"].value); //"left"
          alert(element.getAttributeNode("align").value); //"left"
          alert(element.getAttribute("align")); //"left"

          Text

          文本節點由Text類型表示,包含的是可以照字面解釋的純文本內容。純文本中可以包含轉義后的HTML字符,但不能包含HTML代碼。Text節點具有以下特征:

          • nodeTypeNode.TEXT_NODE,值為3。
          • nodeName的值為#text
          • nodeValue的值為節點所包含的文本。
          • parentNode是一個Element
          • 不支持子節點(沒有子節點)。

          可以通過nodeValue屬性或data屬性訪問Text節點中包含的文本,這兩個屬性中包含的值相同。對nodeValue的修改也會通過data反映出來,反之亦然。使用下列方法可以操作節點中的文本。

          • appendData(text):將text添加到節點的末尾。
          • deleteData(offset, count):從offset指定位置開始刪除count個字符。
          • insertData(offset, text):在offset指定位置插入text
          • replaceData(offset, count, text):用text替換從offset指定的位置開始到offset+count位置處的文本。
          • splitText(offset):從offset指定的位置將當前文本節點分成兩個文本節點。
          • substringData(offset, count):提取從offset指定的位置開始到offset+count為止處的字符串。

          除了這些方法外,文本節點還有一個length屬性,保存著節點中字符的數目。而且,nodeValue.lengthdata.length中也保存著同樣的值。

          修改文本節點的結果會立即得到反映。因此字符串會經過HTML(或XML,取決于文檔類型)編碼。

          使用document.createTextNode()可以創建文本節點,在DOM創建中會講述它。

          Comment

          注釋在DOM中是通過Comment類型來表示的。Comment節點具有下列特征:

          • nodeType為Node.COMMENT_NODE,數值為8。
          • nodeName的值為#comment
          • nodeValue的值是注釋的內容。
          • parentNode可能是DocumentElement
          • 不支持子節點(沒有子節點)。

          Comment類型與Text類型繼承自相同的基類,因此它擁有除splitText()之外的所有字符串操作方法。與Text類型相似,也可以通過nodeValuedata屬性取得注釋的內容。

          獲取<div id="divId"><!--A comment--></div>代碼中的注釋:

          var div=document.getElementById("divId");
          var comment=div.firstChild;
          console.log(comment.data);    // A comment

          如果想創建注釋節點,可以使用document.createComment(data)方法創建。

          var comment=document.createComment("Create a comment node");

          瀏覽器不會識別位于</html>標簽后面的注釋。一定保證訪問的注釋節點位于<html></html>之間。

          CDATASection

          CDATASection類型只針對基于XML文檔,表示的是CDATA區域。與Comment類似,CDATASection類型繼承自Text類型,因此擁有除splitText()之外的所有字符串操作方法。CDATASection節點具有以下特征:

          • nodeTypeCDATA_SECTION_NODE,值為4。
          • nodeName的值為#cdata-section
          • nodeValue的值是CDATA區域中的內容。
          • parentNode可能是DocumentElement
          • 不支持子節點(沒有子節點)。

          CDATA區域只會出現在XML文檔中,因此多數瀏覽器都會把CDATA區域錯誤地解析為CommentElement。以下面的代碼為例:

          <div id="divId"><![CDATA[This is content.]]></div>

          這個例子中的<div>元素應該包含一個CDATASection節點。可是,四大主流瀏覽器無一能夠這樣解析它。即使對于有效的XHTML頁面,瀏覽器也沒有正確地支持嵌入的CDATA區域。

          在真正的XML文檔中,可以使用document.createCDataSection()來創建CDATA區域,只需為其傳入節點的內容即可。

          DocumentType

          DocumentType類型在Web瀏覽器中并不常用。DocumentType包含著與文檔有關的doctype有關的所有信息,它具有下列特征:

          • nodeTypeNode.DOCUMENT_TYPE_NODE,值為10。
          • nodeName的值為doctype的名稱。
          • nodeValue的值為null
          • parentNodeDocument類型。
          • 沒有子節點。

          DOM 1級規定的DocumentType對象不能動態創建,只通過解析文檔代碼的方式來創建。支持DocumentType的瀏覽器會把它保存在document.doctype中。

          DocumentType對象在DOM 1級中有3個屬性:

          • DocumentType.name,文檔類型的名稱。
          • DocumentType.entities,文檔類型描述的實體NamedNodeMap對象。
          • DocumentType.notations,文檔類型描述的符號NamedNodeMap對象。

          瀏覽器中一般是HTMLXHTML類型的文檔。所以entitiesnotations都是空列表。只有name屬性有用。

          <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
          "http://www.w3.org/TR/html4/strict.dtd">

          在這里,DocumentType中的name屬性保存的就是HTML

          console.log(document.doctype.name);    // HTML

          DocumentFragment

          DocumentFragment是文檔片段,一種"輕量級"文檔,可以包含和控制節點,但不像完整文檔那樣占用額外資源。可以將它作為"倉庫"使用。具有下列特征:

          • nodeTypeNode.DOCUMENT_FRAGMENT_NODE,值為11。
          • nodeName的值為#document-fragment
          • nodeValue的值為null
          • parentNode的值為null
          • 子節點可以是ElementProcessingInstructionCommentTextCDATASectionEntityReference

          使用document.createDocumentFragment()方法創建文檔片段,如下所示:

          var fragment=document.createDocumentFragment();

          繼承了Node的所有方法,用于執行針對文檔的DOM操作。可以通過appendChild()insertBefore()添加到文檔中相應位置,但本身不會成為文檔樹的一部分。來看下面的HTML 示例代碼:

          <ul id="ulId"></ul>

          我們給<ul id=ulId></ul>添加3個列表項。可以使用文檔片段來保存創建的列表項,一次性將它們添加到文檔中,避免瀏覽器反復渲染。

          var fragment=document.createDocumentFragment();
          var ul=document.getElementById("myList");
          var li=null;
          for (var i=0; i < 3; i++){
              li=document.createElement("li");
              li.appendChild(document.createTextNode("Item" + (i+1)));
              fragment.appendChild(li);
          }
          ul.appendChild(fragment);

          DOM查找

          現在有一段html頁面模板

          ...
          <style>
              .container {
                  background-color: blue;
                  width: 55%;
                  height: 55%;
              }
          </style>
          ...
          
          <div class="container" id="divId1">Div Text One</div>
          <p class="container" id="pId1">P Text One</p>
          <a class="container" id="aId1">A Text One</a>
          <div class="container" id="divId2">Div Text Two</div>
          <form id="primary-form" action="#" method="get">
              <p>UserName: <input type="text" name="input-name"></p>
              <p class="container">NickName: <input type="text" name="input-name"></p>
              <p>Email: <input type="text" name="input-email"></p>
              <input type="submit" value="Submit">
          </form>
          ...

          在該模板中,我們想要獲取這些標簽元素,可以使用document對象獲取的幾種方法:

          id選擇器

          getElementById(elementId: string): HTMLElement | null;

          該方法返回匹配指定id屬性的元素節點,如果不存在,則返回null

          下面通過id選擇器來獲取idaId1的元素:

          let div=document.getElementById("aId1");
          console.log(div);    // <a class="container" id="aId1">A Text One</a>

          注意:嚴格匹配,包括大小寫。如果寫成document.getElementById("aid1"),輸出為null

          標簽選擇器

          getElementsByTagName(qualifiedName: string): HTMLCollectionOf<Element>;

          該方法返回匹配指定HTML標簽名的元素列表。返回的是一個類似數組對象(HTMLCollection實例),可以實時反映HTML文檔的變化,如果不存在,則返回null

          let inputs=document.getElementsByTagName('input');
          console.log(inputs);    /* HTMLCollection(4) [input, input, input, input, input-name: input, email: input]*/

          這個對象可以使用length屬性獲取元素數量,使用數組語法或item()方法來訪問HTMLCollection對象中的項。

          inputs.length;                // 輸出p標簽的數量
          inputs[0].id;                  // 輸出p標簽集合中第一個元素的id特性的名稱
          inputs.item(0).className;      // 輸出p標簽接種中第一個元素的class特性的名稱

          還可以通過namedItem()方法根據元素的name特性獲取集合中的項。

          var nameOfInput=inputs.namedItem("input-name");

          也可以使用方括號語法來訪問:

          var nameOfInput=inputs["input-name"];

          要想取得文檔中的所有元素,可以向getElementsByTagName()中傳入"*",表示"全部"。

          var allElements=document.getElementsByTagName("*");

          name選擇器

          getElementsByName(elementName: string): NodeListOf<HTMLElement>;

          該方法返回匹配name屬性的所有元素,返回值是NodeList,如果不存在,則返回null

          var names=document.getElementsByName("input-name");
          console.log(names);

          注意,這個選擇器在不同瀏覽器的效果是不同的,比如在IE和Opera瀏覽器下,這個方法也會返回id屬性為這個值的元素。在使用的時候,應該小心使用,盡量保證name不和其它元素的id一致。

          類選擇器

          getElementsByClassName(classNames: string): HTMLCollectionOf<Element>;是HTML5中添加的方法。

          該方法返回匹配class屬性的所有元素,返回值是HTMLCollection,如果不存在,則返回null

          // 獲取所有class中同時包含'red'和'test'的元素
          var classes=document.getElementsByClassName("container");
          console.log(classes);

          可以接收包含一個或多個類名的字符串,傳入的多個類名的先后順序不重要。

          Selectors API

          W3C發起指定的標準,可使瀏覽器支持CSS查詢。Selectors API的核心是兩個方法:querySelector()querySelectorAll()。兼容的瀏覽器中通過DocumentElement節點類型的實例進行調用。

          querySelector()方法

          querySelector<E extends Element=Element>(selectors: string): E | null;

          該方法返回匹配指定選擇符的第一個HTMLElement元素,如果不存在,則返回null。傳入的selectors必須是有效的CSS選擇器;如果選擇器不合法,會引發SYNTAX_ERR異常。

          document.querySelector("#aId1");    // 取得Id為"aId1"的元素
          document.querySelector("p");    // 取得p元素
          document.querySelector(".container");    // 取得類為"container"的第一個元素
          document.querySelector("..selector");    // 引發'SYNTAX_ERR'異常(Uncaught DOMException:Failed to execute 'querySelector on 'Document': '..selector' is not a valid selector. 意思是'..selector'不是一個有效的選擇。)

          DocumentElement都可以調用querySelector()方法,只是Document會在文檔元素的范圍內查找匹配的元素;Element只會在該元素后代元素的范圍內查找匹配的元素。

          querySelectorAll()方法

          querySelectorAll<E extends Element=Element>(selectors: string): NodeListOf<E>;

          該方法返回匹配指定選擇符的元素列表,返回的對象是NodeList,如果不存在,則返回空的NodeList。傳入的selectors必須是有效的CSS選擇器;如果選擇器不合法,會引發SYNTAX_ERR異常。

          // 獲取id為"primary-form"中所有<p>元素
          document.getElementById("primary-form").querySelectorAll("p");
          // 獲取類為"container"的所有元素
          document.querySelectorAll(".container");
          // 獲取所有<form>元素中的所有<p>元素
          document.querySelectorAll("form p");

          matches()方法

          Selectors API Level 2規范為Element類型新增了一個方法:

          matches(selectors: string): boolean;

          該方法判斷當前DOM節點是否能完全匹配指定選擇符,如果匹配成功,返回true;匹配失敗,返回false

          var elems=document.getElementsByTagName('p');
          for (var i=0; i < elems.length; i++) {
              // 獲取匹配'container'類選擇符的dom節點 
              if (elems.item(i).matches('.container')) {
                  console.log('The ' + elems.item(i).textContent + ' is container');
              }
          }
          /*The P Text One is container
          The NickName:  is container*/

          注意,有些供應商會有自己實驗性方法在matchesSelector()方法之前加些前綴。如果想使用這種方法,可以編寫一個包裝函數。

          function matchesSelector(element, selector){
              if (element.matches) {
                  // 標準方法
                  return element.matches(selector);
              } else if (element.matchesSelector){
                  return element.matchesSelector(selector);
              } else if (element.msMatchesSelector){      // IE 9+支持
                  return element.msMatchesSelector(selector);
              } else if (element.mozMatchesSelector){     // Firefox 3.6+支持 
                  return element.mozMatchesSelector(selector);
              } else if (element.webkitMatchesSelector){  // Safari 5+和Chrome支持
                  return element.webkitMatchesSelector(selector);
              } else {
                  throw new Error("Not supported.");
              }
          }
          if (matchesSelector(document.body, ".container")){
              //執行操作
          }

          當有的瀏覽器不支持Element.matches()Element.matchesSelector(),但支持document.querySelectorAll()方法,可以有替代方案:

          if (!Element.prototype.matches) {
              Element.prototype.matches= Element.prototype.matchesSelector || 
                  Element.prototype.mozMatchesSelector ||
                  Element.prototype.msMatchesSelector || 
                  Element.prototype.oMatchesSelector || 
                  Element.prototype.webkitMatchesSelector ||
                  function(s) {
                      var matches=(this.document || this.ownerDocument).querySelectorAll(s),
                          i=matches.length;
                      while (--i >=0 && matches.item(i) !==this) {}
                      return i > -1;            
                  };
          }

          DOM遍歷

          Node節點提供了幾種屬性,用于訪問DOM節點。

          parentNode

          node.parentNode屬性用于返回指定節點的父節點。除document外,所有節點都有父節點,document對象的父節點為null。示例如下:

          document.getElementById('divId2').parentNode;

          childNodes

          node.childNodes屬性用于返回指定節點的子結點的Node對象集合。示例如下:

          document.getElementById('primary-form').childNodes;

          firstChild/lastChild

          node.firstChild屬性用于訪問第一個子節點;node.lastChild屬性用于訪問最后一個子節點。如果要訪問的節點不存在,則返回null。示例如下:

          document.getElementById('primary-form').firstChild
          document.getElementById('primary-form').lastChild;

          previousSibling/nextSibling

          node.previousSibling屬性用于訪問之前的同級節點;node.nextSibling屬性用于訪問之后的同級節點。具有相同父節點為同級節點,之前或之后表示它們在文檔中出現的順序。實例如下:

          document.getElementById('divId2').previousSibling;
          document.getElementById('divId2').nextSibling;

          ownerDocument

          node.ownerDocument屬性用于返回元素的根節點,即:文檔對象(Document)。通過這個屬性,我們能夠直接訪問根節點而不必層層遍歷。實例如下:

          document.getElementById('divId2').ownerDocument;

          Element Traversal

          Element Traversal API 為DOM元素添加了以下5個屬性。

          • childElementCount:返回子元素(不包括文本節點和注釋)的格式。
          • firstElementChild:指向第一個子元素;firstChild的元素版。
          • lastElementChild:指向最后一個子元素;lastChild的元素版。
          • previousElementSibling:指向前一個同輩元素;previousSibling的元素版。
          • nextElementSibling:指向后一個同輩元素;nextSibling的元素版。

          支持的瀏覽器為DOM元素添加了這些屬性,利用這些元素不必擔心空白文檔節點,從而可以更方便地查找DOM元素。

          DOM操作

          因為關系節點都是只讀的,所以DOM提供了一些操作節點的方法。

          appendChild()

          node.appendChild(newChild)方法用于向childNodes列表的末尾添加一個節點并返回新增的節點。

          var returnedNode=div.appendChild(newNode);

          insertBefore()

          node.insertBefore(newChild, refChild)方法會在指定的參照節點refChild之前插入新節點newChild。插入節點后,被插入的節點會變成參照節點的前一個同胞節點(previousSibling),同時被方法返回。如果refChildnull,則insertBefore()appendChild()執行相同的操作。

          var returnedNode=div.insertBefore(newNode, div.lastChild);

          replaceChild()

          node.replaceChild(newChild, oldChild)方法將要替換的節點oldChild移除,并將要插入的節點newChild插入并占據其位置。實例如下:

          document.getElementById('divId2').replaceChild(newnode, oldnode);

          在使用replaceChild()插入一個節點時,該節點的所有關系指針都會從被它替換的節點復制過來。被替換的節點仍然還在文檔中,但它在文檔中已經沒有自己的位置了。

          removeChild()

          而如果只想移除而非替換節點,可以使用node.removeChild(oldChild)方法,該方法將要移除的節點oldChild移除,并返回移除的節點。

          var removedNode=node.removeChild(node.firstChild);

          與使用replaceChild()方法一樣,通過removeChild()移除的節點仍然為文檔所有,只不過在文檔中已經沒有了自己的位置。

          上面介紹的四種方法操作的都是某個節點的子節點,要使用這幾個方法必須先取得父節點。另外,并不是所有類型的節點都有子節點,如果在不支持子節點的節點上調用這些方法,將會導致錯誤發生。

          DOM創建

          DOM節點創建最常用的便是document.createElement()document.createTextNode()方法。

          createElement()

          document.createElement(tagName)方法根據指定tagName標簽名創建新元素節點,返回一個HTMLElement對象。標簽名在HTML文檔中不區分大小寫,在XML(包括XHTML)文檔中區分大小寫。例如,創建一個<p>元素。

          var p=document.createElement('p');

          在使用createElement()方法創建新元素的同時,也為新元素設置了ownerDocument屬性。

          createTextNode()

          document.createTextNode(data: string)方法根據指定data文本創建新文本節點。作為參數的文本按照HTML或XML的格式進行編碼。

          var textNode=document.createTextNode("<h4>Hello </h4> world!");

          在創建新文本節點的同時,也會為其設置ownerDocument屬性。

          cloneNode()

          node.cloneNode(deep)方法用于對調用這個方法的節點創建一個完全相同的副本。deep是布爾值,設置是否執行深復制。默認為false,執行淺復制(只復制節點本身);當為true時,執行深復制(復制節點及其整個子節點樹)。

          var node=document.getElementById('divId2').lastChild.cloneNode(true);

          這些用于創建節點和復制節點的方法,創建或復制的節點并不會出現在文檔中,需要通過appendChild()insertBefore()replaceChild()將它添加到文檔中。

          document.getElementById('divId2').appendChild(node);

          不管是createElement()createTextNode()或者cloneNode()三種的哪種方法,創建新的節點都未被添加到文檔樹中。可以使用上面介紹的appendChild()insertBefore()replaceChild()方法將新節點添加到文檔樹中。

          一旦將節點添加到文檔樹中,瀏覽器就會立即呈現。

          一旦使用appendChild()等方法插入相鄰的同胞文本節點時,會導致相鄰文本節點混亂。

          而在一個包含兩個或多個文本節點的父元素上調用normalize()方法,就會將所有文本節點合并成一個節點。

          var element=document.createElement("div");
          element.className="message";
          var textNode1=document.createTextNode("Hello, ");
          element.appendChild(textNode1);
          var textNode2=document.createTextNode("Pandora!");
          element.appendChild(textNode2);
          document.body.appendChild(element);
          console.log(element.childNodes.length);  // 2
          element.normalize();
          console.log(element.childNodes.length);  // 1
          console.log(element.firstChild.nodeValue);  // "Hello, Pandora!"

          瀏覽器在解析文檔時永遠不會創建相鄰的文本節點。這種情況只會作為執行DOM操作的結果出現。

          還有一個與normalize()相反的方法splitText(offset):將一個文本節點分成兩個文本節點。

          Submit 對象

          Submit 對象代表 HTML 表單中的一個提交按鈕 (submit button)。

          在 HTML 表單中 <input type="submit"> 標簽每出現一次,一個 Submit 對象就會被創建。

          在表單提交之前,觸發 onclick 事件句柄,并且一個句柄可以通過返回 fasle 來取消表單提交。

          您可以通過遍歷表單的 elements[] 數組來訪問某個提交按鈕,或者通過使用document.getElementById()。

          Submit 對象屬性

          W3C: W3C 標準。

          屬性描述W3C
          disabled設置或返回提交按鈕是否應被禁用。Yes
          form返回一個對包含此提交按鈕的表單的引用。Yes
          name設置或返回提交按鈕的名稱。Yes
          type返回提交按鈕的表單元素類型。Yes
          value設置或返回在提交按鈕上顯示的文本。Yes

          標準屬性和事件

          Submit 對象同樣支持標準的 屬性 和 事件。

          如您還有不明白的可以在下面與我留言或是與我探討QQ群308855039,我們一起飛!

          Select 對象

          Select 對象代表 HTML 表單中的一個下拉列表。

          在 HTML 表單中,<select> 標簽每出現一次,一個 Select 對象就會被創建。

          您可通過遍歷表單的 elements[] 數組來訪問某個 Select 對象,或者使用 document.getElementById()。

          Select 對象集合

          W3C: W3C 標準。

          集合描述W3C
          options返回包含下拉列表中的所有選項的一個數組。Yes

          Select 對象屬性

          屬性描述W3C
          disabled設置或返回是否應禁用下拉列表。Yes
          form返回對包含下拉列表的表單的引用。Yes
          length返回下拉列表中的選項數目。Yes
          multiple設置或返回是否選擇多個項目。Yes
          name設置或返回下拉列表的名稱。Yes
          selectedIndex設置或返回下拉列表中被選項目的索引號。Yes
          size設置或返回下拉列表中的可見行數。Yes
          type返回下拉列表的表單類型。Yes

          Select 對象方法

          方法描述W3C
          add()向下拉列表添加一個選項。Yes
          remove()從下拉列表中刪除一個選項。Yes

          標準屬性和事件

          Select 對象同樣支持標準的 屬性 和 事件。

          如您還有不明白的可以在下面與我留言或是與我探討QQ群308855039,我們一起飛!


          主站蜘蛛池模板: 无码视频一区二区三区在线观看 | 国产色精品vr一区区三区| 国产激情精品一区二区三区 | 成人精品一区二区三区校园激情| 国产小仙女视频一区二区三区| 国产色精品vr一区区三区| 韩国理伦片一区二区三区在线播放| 亚洲一区二区精品视频| 国产乱码精品一区二区三区四川人| 亚洲国产综合精品一区在线播放| 亚洲AV无码国产一区二区三区 | 亚洲国产成人精品无码一区二区| 亚洲AⅤ视频一区二区三区| 亚洲AV无码一区二区三区牲色| 国产一区二区福利| 国产乱码伦精品一区二区三区麻豆 | 国产精品久久久久一区二区三区 | 亚洲欧美日韩中文字幕在线一区| 手机看片一区二区| 福利一区二区视频| 冲田杏梨AV一区二区三区| 中文字幕一区二区三区精彩视频| 综合久久久久久中文字幕亚洲国产国产综合一区首 | 久久久久人妻一区精品性色av| 国产av福利一区二区三巨| 在线日韩麻豆一区| 国产精品一区在线麻豆| 99精品国产高清一区二区| 精品少妇一区二区三区视频| 亚洲av高清在线观看一区二区| 在线|一区二区三区| 亚洲AV香蕉一区区二区三区| 91精品国产一区| 亚洲伦理一区二区| 国产suv精品一区二区33| 国产无套精品一区二区| 国产一区二区三区高清视频| 婷婷国产成人精品一区二| 国偷自产视频一区二区久| 日韩美女在线观看一区| 丰满爆乳无码一区二区三区|