DOM編程之API總結(jié)篇

原文 鏈接

關(guān)注公眾號(hào)獲取更多資訊

一、基本類(lèi)型介紹


1.1 Node類(lèi)型


  • DOM1級(jí)定義了一個(gè)Node接口,該接口由DOM中所有節(jié)點(diǎn)類(lèi)型實(shí)現(xiàn)。這個(gè)Node接口在JS中是作為Node類(lèi)型實(shí)現(xiàn)的。在IE9以下版本無(wú)法訪問(wèn)到這個(gè)類(lèi)型,JS中所有節(jié)點(diǎn)都繼承自Node類(lèi)型,都共享著相同的基本屬性和方法
  • Node有一個(gè)屬性nodeType表示Node的類(lèi)型,它是一個(gè)整數(shù),其數(shù)值分別表示相應(yīng)的Node類(lèi)型
節(jié)點(diǎn)類(lèi)型
Node類(lèi)型
  • 假設(shè)我們要判斷一個(gè)Node是不是元素,我們可以這樣判斷
if(someNode.nodeType == 1){
console.log("Node is a element");
}
  • 這些Node類(lèi)型中,我們最常用的就是elementtextattributecommentdocumentdocument_fragment這幾種類(lèi)型
1.2 Element類(lèi)型

Element類(lèi)型
  • Element提供了對(duì)元素標(biāo)簽名,子節(jié)點(diǎn)和特性的訪問(wèn),我們常用HTML元素比如divspana等標(biāo)簽就是element中的一種。

  • Element有下面幾條特性:

    • nodeType1
    • nodeName為元素標(biāo)簽名,tagName也是返回標(biāo)簽名
    • nodeValuenull
    • parentNode可能是DocumentElement
    • 子節(jié)點(diǎn)可能是 ElementTextCommentProcessing_InstructionCDATASectionEntityReference
1.3 Text類(lèi)型

Text類(lèi)型
  • Text表示文本節(jié)點(diǎn),它包含的是純文本內(nèi)容,不能包含html代碼,但可以包含轉(zhuǎn)義后的html代碼。Text有下面的特性:
    • nodeType3
    • nodeName#text
    • nodeValue為文本內(nèi)容
    • parentNode是一個(gè)Element
    • 沒(méi)有子節(jié)點(diǎn)
1.4 Attr類(lèi)型

Attr類(lèi)型
  • Attr類(lèi)型表示元素的特性,相當(dāng)于元素的attributes屬性中的節(jié)點(diǎn),它有下面的特性:
    • nodeType值為2
    • nodeName是特性的名稱(chēng)
    • nodeValue是特性的值
    • parentNodenull
1.5 Comment類(lèi)型

  • Comment表示HTML文檔中的注釋?zhuān)邢旅娴膸追N特征:
    • nodeType為8
    • nodeName#comment
    • nodeValue為注釋的內(nèi)容
    • parentNode可能是DocumentElement
    • 沒(méi)有子節(jié)點(diǎn)
1.6 Document

Document類(lèi)型
  • Document表示文檔,在瀏覽器中,document對(duì)象是HTMLDocument的一個(gè)實(shí)例,表示整個(gè)頁(yè)面,它同時(shí)也是window對(duì)象的一個(gè)屬性。Document有下面的特性:
    • nodeType9
    • nodeName#document
    • nodeValuenull
    • parentNodenull
    • 子節(jié)點(diǎn)可能是一個(gè)DocumentTypeElement
1.7 DocumentFragment類(lèi)型

  • DocumentFragment是所有節(jié)點(diǎn)中唯一一個(gè)沒(méi)有對(duì)應(yīng)標(biāo)記的類(lèi)型,它表示一種輕量級(jí)的文檔,可能當(dāng)作一個(gè)臨時(shí)的倉(cāng)庫(kù)用來(lái)保存可能會(huì)添加到文檔中的節(jié)點(diǎn)。DocumentFragment有下面的特性:

    • nodeType11
    • nodeName#document-fragment
    • nodeValuenull
    • parentNodenull
  • 我們簡(jiǎn)單地介紹了幾種常見(jiàn)的Node類(lèi)型,要記住,HTML中的節(jié)點(diǎn)并不只是包括元素節(jié)點(diǎn),它還包括文本節(jié)點(diǎn),注釋節(jié)點(diǎn)等等。在這里我們只是簡(jiǎn)單地說(shuō)明了幾種常見(jiàn)的節(jié)點(diǎn).

二、 DOM提供的幾個(gè)屬性


2.1 childNodes屬性


  • 在一棵節(jié)點(diǎn)樹(shù)上,childNodes屬性可以用來(lái)獲取任何一個(gè)元素的所有子節(jié)點(diǎn),它是一個(gè)包含這個(gè)元素全部子元素的數(shù)組
element.childNodes

2.2 nodeType屬性


  • 節(jié)點(diǎn)之間的關(guān)系構(gòu)成了節(jié)點(diǎn)層次,html 頁(yè)面的可以畫(huà)出一個(gè)以html標(biāo)簽為根節(jié)點(diǎn)的樹(shù)形結(jié)構(gòu)
    DOM 會(huì)把文檔看作是一棵樹(shù),同時(shí)定義了很多方法來(lái)操作這棵數(shù)中的每一個(gè)元素(節(jié)點(diǎn))
<html lang="en">
<head>
    <title>Document</title>
</head>
<body>
    <p>hello world!!!</p>
</body>
</html>

[圖片上傳失敗...(image-635720-1545535313683)]

  • 每一個(gè)節(jié)點(diǎn)都有nodeType屬性
node.nodeType
  • nodeType屬性總共有12中可能取值,但其中僅有3種有實(shí)用價(jià)值
    • 元素節(jié)點(diǎn)的nodeType屬性值是1
    • 屬性節(jié)點(diǎn)的nodeType屬性值是2
    • 文本節(jié)點(diǎn)的nodeType屬性值是3
description.firstChild.nodeValue = text;

2.3 nodeValue屬性


  • nodeValue屬性
    • 如果想改變一個(gè)文本節(jié)點(diǎn)的值,那就使用DOM提供的nodeValue,它用來(lái)得到一個(gè)節(jié)點(diǎn)的值 node.nodeValue
    • 需要注意:nodeValue屬性獲取對(duì)象的值時(shí),得到的并不是包含在這個(gè)段落里的文本
    • nodeValue屬性不僅可以用來(lái)檢測(cè)節(jié)點(diǎn)的值,還可以設(shè)置節(jié)點(diǎn)的值

2.4 firstChild和lastChild屬性


  • 數(shù)組元素childNodes[0]有個(gè)更直觀的同義詞。無(wú)論如何,只要訪問(wèn)childNodes數(shù)組的第一個(gè)元素,都可以把它寫(xiě)成firstChild
node.firstChild

與下面等價(jià)

node.childNodes[0]
  • DOM還提供了一個(gè)與之對(duì)應(yīng)的lastChild屬性
node.lastChild

三、節(jié)點(diǎn)創(chuàng)建型API


  • 在這里,我將常用的DOM操作api進(jìn)行分類(lèi),首先要介紹的是創(chuàng)建型的api。這一類(lèi)型的api,簡(jiǎn)而言之就是用來(lái)創(chuàng)建節(jié)點(diǎn)的

3.1 createElement


  • createElement通過(guò)傳入指定的一個(gè)標(biāo)簽名來(lái)創(chuàng)建一個(gè)元素,如果傳入的標(biāo)簽名是一個(gè)未知的,則會(huì)創(chuàng)建一個(gè)自定義的標(biāo)簽,注意:IE8以下瀏覽器不支持自定義標(biāo)簽

var div = document.createElement("div");
  • 使用createElement要注意:通過(guò)createElement創(chuàng)建的元素并不屬于html文檔,它只是創(chuàng)建出來(lái),并未添加到html文檔中,要調(diào)用appendChildinsertBefore等方法將其添加到HTML文檔樹(shù)中

3.2 createTextNode


  • createTextNode用來(lái)創(chuàng)建一個(gè)文本節(jié)點(diǎn),用法如下

var textNode = document.createTextNode("一個(gè)TextNode");
  • createTextNode接收一個(gè)參數(shù),這個(gè)參數(shù)就是文本節(jié)點(diǎn)中的文本,和createElement一樣,創(chuàng)建后的文本節(jié)點(diǎn)也只是獨(dú)立的一個(gè)節(jié)點(diǎn),同樣需要appendChild將其添加到HTML文檔樹(shù)中

3.3 cloneNode

  • cloneNode是用來(lái)返回調(diào)用方法的節(jié)點(diǎn)的一個(gè)副本,它接收一個(gè)bool參數(shù),用來(lái)表示是否復(fù)制子元素,使用如下:
var parent = document.getElementById("parentElement"); 
var parent2 = parent.cloneNode(true);// 傳入true
parent2.id = "parent2";
  • 這段代碼通過(guò)cloneNode復(fù)制了一份parent元素,其中cloneNode的參數(shù)為true,表示parent的子節(jié)點(diǎn)也被復(fù)制,如果傳入false,則表示只復(fù)制了parent節(jié)點(diǎn)
<div id="parent">
    我是父元素的文本
    <br/>
    <span>
        我是子元素
    </span>
</div>
<button id="btnCopy">復(fù)制</button>

var parent = document.getElementById("parent");
document.getElementById("btnCopy").onclick = function(){
    var parent2 = parent.cloneNode(true);
    parent2.id = "parent2";
    document.body.appendChild(parent2);
}
  • 這段代碼很簡(jiǎn)單,主要是綁定button事件,事件內(nèi)容是復(fù)制了一個(gè)parent,修改其id,然后添加到文檔中

  • 這里有幾點(diǎn)要注意:

    • createElement一樣,cloneNode創(chuàng)建的節(jié)點(diǎn)只是游離有html文檔外的節(jié)點(diǎn),要調(diào)用appendChild方法才能添加到文檔樹(shù)中
    • 如果復(fù)制的元素有id,則其副本同樣會(huì)包含該id,由于id具有唯一性,所以在復(fù)制節(jié)點(diǎn)后必須要修改其id
    • 調(diào)用接收的bool參數(shù)最好傳入,如果不傳入該參數(shù),不同瀏覽器對(duì)其默認(rèn)值的處理可能不同
  • 除此之外,我們還有一個(gè)需要注意的點(diǎn):

    • 如果被復(fù)制的節(jié)點(diǎn)綁定了事件,則副本也會(huì)跟著綁定該事件嗎?這里要分情況討論:
      • 如果是通過(guò)addEventListener或者比如onclick進(jìn)行綁定事件,則副本節(jié)點(diǎn)不會(huì)綁定該事件
      • 如果是內(nèi)聯(lián)方式綁定比如

<div onclick="showParent()"></div>

  • 這樣的話,副本節(jié)點(diǎn)同樣會(huì)觸發(fā)事件

3.4 createDocumentFragment


  • createDocumentFragment方法用來(lái)創(chuàng)建一個(gè)DocumentFragment。在前面我們說(shuō)到DocumentFragment表示一種輕量級(jí)的文檔,它的作用主要是存儲(chǔ)臨時(shí)的節(jié)點(diǎn)用來(lái)準(zhǔn)備添加到文檔中

  • createDocumentFragment方法主要是用于添加大量節(jié)點(diǎn)到文檔中時(shí)會(huì)使用到。假設(shè)要循環(huán)一組數(shù)據(jù),然后創(chuàng)建多個(gè)節(jié)點(diǎn)添加到文檔中

<ul id="list"></ul>
<input type="button" value="添加多項(xiàng)" id="btnAdd" />

document.getElementById("btnAdd").onclick = function(){
    var list = document.getElementById("list");
    for(var i = 0;i < 100; i++){
        var li = document.createElement("li");
        li.textContent = i;
        list.appendChild(li);
    }
}
  • 這段代碼將按鈕綁定了一個(gè)事件,這個(gè)事件創(chuàng)建了100個(gè)li節(jié)點(diǎn),然后依次將其添加HTML文檔中。這樣做有一個(gè)缺點(diǎn):每次一創(chuàng)建一個(gè)新的元素,然后添加到文檔樹(shù)中,這個(gè)過(guò)程會(huì)造成瀏覽器的回流。所謂回流簡(jiǎn)單說(shuō)就是指元素大小和位置會(huì)被重新計(jì)算,如果添加的元素太多,會(huì)造成性能問(wèn)題。這個(gè)時(shí)候,就是使用createDocumentFragment了

  • DocumentFragment不是文檔樹(shù)的一部分,它是保存在內(nèi)存中的,所以不會(huì)造成回流問(wèn)題。我們修改上面的代碼如下

document.getElementById("btnAdd").onclick = function(){
    var list = document.getElementById("list"); 
    var fragment = document.createDocumentFragment();

    for(var i = 0;i < 100; i++){
      var li = document.createElement("li");
        li.textContent = i;
        fragment.appendChild(li);
    }

    list.appendChild(fragment);
}
  • 優(yōu)化后的代碼主要是創(chuàng)建了一個(gè)fragment,每次生成的li節(jié)點(diǎn)先添加到fragment,最后一次性添加到list

3.5 創(chuàng)建型API總結(jié)


  • 創(chuàng)建型api主要包括createElementcreateTextNodecloneNodecreateDocumentFragment四個(gè)方法,需要注意下面幾點(diǎn):

    • 它們創(chuàng)建的節(jié)點(diǎn)只是一個(gè)孤立的節(jié)點(diǎn),要通過(guò)appendChild添加到文檔中
    • cloneNode要注意如果被復(fù)制的節(jié)點(diǎn)是否包含子節(jié)點(diǎn)以及事件綁定等問(wèn)題
    • 使用createDocumentFragment來(lái)解決添加大量節(jié)點(diǎn)時(shí)的性能問(wèn)題

四、頁(yè)面修改型API


  • 前面我們提到創(chuàng)建型api,它們只是創(chuàng)建節(jié)點(diǎn),并沒(méi)有真正修改到頁(yè)面內(nèi)容,而是要調(diào)用appendChild來(lái)將其添加到文檔樹(shù)中。我在這里將這類(lèi)會(huì)修改到頁(yè)面內(nèi)容歸為一類(lèi)。
    修改頁(yè)面內(nèi)容的api主要包括:appendChildinsertBeforeremoveChildreplaceChild

4.1 appendChild


  • appendChild我們?cè)谇懊嬉呀?jīng)用到多次,就是將指定的節(jié)點(diǎn)添加到調(diào)用該方法的節(jié)點(diǎn)的子元素的末尾。調(diào)用方法如下:
parent.appendChild(child);
  • child節(jié)點(diǎn)將會(huì)作為parent節(jié)點(diǎn)的最后一個(gè)子節(jié)點(diǎn)

  • appendChild這個(gè)方法很簡(jiǎn)單,但是還有有一點(diǎn)需要注意:如果被添加的節(jié)點(diǎn)是一個(gè)頁(yè)面中存在的節(jié)點(diǎn),則執(zhí)行后這個(gè)節(jié)點(diǎn)將會(huì)添加到指定位置,其原本所在的位置將移除該節(jié)點(diǎn),也就是說(shuō)不會(huì)同時(shí)存在兩個(gè)該節(jié)點(diǎn)在頁(yè)面上,相當(dāng)于把這個(gè)節(jié)點(diǎn)移動(dòng)到另一個(gè)地方

<div id="child">
    要被添加的節(jié)點(diǎn)
</div>
<br/>
<br/>
<br/>
<div id="parent">
    要移動(dòng)的位置
</div>      
<input id="btnMove" type="button" value="移動(dòng)節(jié)點(diǎn)" />

document.getElementById("btnMove").onclick = function(){
    var child = document.getElementById("child");
    document.getElementById("parent").appendChild(child);
}

  • 這段代碼主要是獲取頁(yè)面上的child節(jié)點(diǎn),然后添加到指定位置,可以看到原本的child節(jié)點(diǎn)被移動(dòng)到parent中了。
    這里還有一個(gè)要注意的點(diǎn):如果child綁定了事件,被移動(dòng)時(shí),它依然綁定著該事件

4.2 insertBefore


  • insertBefore用來(lái)添加一個(gè)節(jié)點(diǎn)到一個(gè)參照節(jié)點(diǎn)之前,用法如下

parentNode.insertBefore(newNode,refNode);
  • parentNode表示新節(jié)點(diǎn)被添加后的父節(jié)點(diǎn)
  • newNode表示要添加的節(jié)點(diǎn)
  • refNode表示參照節(jié)點(diǎn),新節(jié)點(diǎn)會(huì)添加到這個(gè)節(jié)點(diǎn)之前
<div id="parent">
    父節(jié)點(diǎn)
    <div id="child">                
        子元素
    </div>
</div>
<input type="button" id="insertNode" value="插入節(jié)點(diǎn)" />

var parent = document.getElementById("parent");
var child = document.getElementById("child");
document.getElementById("insertNode").onclick = function(){
    var newNode = document.createElement("div");
    newNode.textContent = "新節(jié)點(diǎn)"
    parent.insertBefore(newNode,child);
}
  • 這段代碼創(chuàng)建了一個(gè)新節(jié)點(diǎn),然后添加到child節(jié)點(diǎn)之前

  • appendChild一樣,如果插入的節(jié)點(diǎn)是頁(yè)面上的節(jié)點(diǎn),則會(huì)移動(dòng)該節(jié)點(diǎn)到指定位置,并且保留其綁定的事件。

  • 關(guān)于第二個(gè)參數(shù)參照節(jié)點(diǎn)還有幾個(gè)注意的地方:

    • refNode是必傳的,如果不傳該參數(shù)會(huì)報(bào)錯(cuò)
    • 如果refNodeundefinednull,則insertBefore會(huì)將節(jié)點(diǎn)添加到子元素的末尾

4.3 removeChild


  • removeChild顧名思義,就是刪除指定的子節(jié)點(diǎn)并返回,用法如下

var deletedChild = parent.removeChild(node);

  • deletedChild指向被刪除節(jié)點(diǎn)的引用,它等于node,被刪除的節(jié)點(diǎn)仍然存在于內(nèi)存中,可以對(duì)其進(jìn)行下一步操作。

  • 注意:如果被刪除的節(jié)點(diǎn)不是其子節(jié)點(diǎn),則程序?qū)?huì)報(bào)錯(cuò)。我們可以通過(guò)下面的方式來(lái)確保可以刪除:

if(node.parentNode){
    node.parentNode.removeChild(node);
}
  • 通過(guò)節(jié)點(diǎn)自己獲取節(jié)點(diǎn)的父節(jié)點(diǎn),然后將自身刪除

4.4 replaceChild


  • replaceChild用于使用一個(gè)節(jié)點(diǎn)替換另一個(gè)節(jié)點(diǎn),用法如下

parent.replaceChild(newChild,oldChild);

  • newChild是替換的節(jié)點(diǎn),可以是新的節(jié)點(diǎn),也可以是頁(yè)面上的節(jié)點(diǎn),如果是頁(yè)面上的節(jié)點(diǎn),則其將被轉(zhuǎn)移到新的位置
  • oldChild是被替換的節(jié)點(diǎn)

4.5 頁(yè)面修改型API總結(jié)


  • 頁(yè)面修改型api主要是這四個(gè)接口,要注意幾個(gè)特點(diǎn)
    • 不管是新增還是替換節(jié)點(diǎn),如果新增或替換的節(jié)點(diǎn)是原本存在頁(yè)面上的,則其原來(lái)位置的節(jié)點(diǎn)將被移除,也就是說(shuō)同一個(gè)節(jié)點(diǎn)不能存在于頁(yè)面的多個(gè)位置
    • 節(jié)點(diǎn)本身綁定的事件會(huì)不會(huì)消失,會(huì)一直保留著

五、節(jié)點(diǎn)查詢型API


  • 節(jié)點(diǎn)查詢型API也是非常常用的

5.1 document.getElementById


  • 這個(gè)接口很簡(jiǎn)單,根據(jù)元素id返回元素,返回值是Element類(lèi)型,如果不存在該元素,則返回null

  • 使用這個(gè)接口有幾點(diǎn)要注意:

    • 元素的Id是大小寫(xiě)敏感的,一定要寫(xiě)對(duì)元素的id
    • HTML文檔中可能存在多個(gè)id相同的元素,則返回第一個(gè)元素
    • 只從文檔中進(jìn)行搜索元素,如果創(chuàng)建了一個(gè)元素并指定id,但并沒(méi)有添加到文檔中,則這個(gè)元素是不會(huì)被查找到的

5.2 document.getElementsByTagName


  • 這個(gè)接口根據(jù)元素標(biāo)簽名獲取元素,返回一個(gè)即時(shí)的HTMLCollection類(lèi)型,什么是即時(shí)的HTMLCollection類(lèi)型呢?
<div>div1</div>
<div>div2</div>
        
<input type="button" value="顯示數(shù)量" id="btnShowCount"/>
<input type="button" value="新增div" id="btnAddDiv"/> 

var divList = document.getElementsByTagName("div");
document.getElementById("btnAddDiv").onclick = function(){
    var div = document.createElement("div");
    div.textContent ="div" + (divList.length+1);
    document.body.appendChild(div);
}
    
document.getElementById("btnShowCount").onclick = function(){
        alert(divList.length);
}
  • 這段代碼中有兩個(gè)按鈕,一個(gè)按鈕是顯示HTMLCollection元素的個(gè)數(shù),另一個(gè)按鈕可以新增一個(gè)div標(biāo)簽到文檔中。前面提到HTMLCollcetion元素是即時(shí)的表示該集合是隨時(shí)變化的,也就是是文檔中有幾個(gè)div,它會(huì)隨時(shí)進(jìn)行變化,當(dāng)我們新增一個(gè)div后,再訪問(wèn)HTMLCollection時(shí),就會(huì)包含這個(gè)新增的div

  • 使用document.getElementsByTagName這個(gè)方法有幾點(diǎn)要注意

    • 如果要對(duì)HTMLCollection集合進(jìn)行循環(huán)操作,最好將其長(zhǎng)度緩存起來(lái),因?yàn)槊看窝h(huán)都會(huì)去計(jì)算長(zhǎng)度,暫時(shí)緩存起來(lái)可以提高效率
    • 如果沒(méi)有存在指定的標(biāo)簽,該接口返回的不是null,而是一個(gè)空的HTMLCollection
    • “*”表示所有標(biāo)簽

5.3 document.getElementsByName


  • getElementsByName主要是通過(guò)指定的name屬性來(lái)獲取元素,它返回一個(gè)即時(shí)的NodeList對(duì)象。一般用于獲取表單元素的·name·屬性

  • 使用這個(gè)接口主要要注意幾點(diǎn):

    • 返回對(duì)象是一個(gè)即時(shí)的NodeList,它是隨時(shí)變化的
    • HTML元素中,并不是所有元素都有name屬性,比如div是沒(méi)有name屬性的,但是如果強(qiáng)制設(shè)置div的name`屬性,它也是可以被查找到的
    • IE中,如果id設(shè)置成某個(gè)值,然后傳入getElementsByName的參數(shù)值和id值一樣,則這個(gè)元素是會(huì)被找到的,所以最好不好設(shè)置同樣的值給idname

5.4 document.getElementsByClassName


  • 這個(gè)API是根據(jù)元素的class返回一個(gè)即時(shí)的HTMLCollection,用法如下
var elements = document.getElementsByClassName(names);
  • 這個(gè)接口有下面幾點(diǎn)要注意:
    • 返回結(jié)果是一個(gè)即時(shí)的HTMLCollection,會(huì)隨時(shí)根據(jù)文檔結(jié)構(gòu)變化
    • IE9以下瀏覽器不支持
    • 如果要獲取2個(gè)以上classname,可傳入多個(gè)classname,每個(gè)用空格相隔,例如

var elements = document.getElementsByClassName("test1 test2");

5.5 document.querySelector和document.querySelectorAll


  • 這兩個(gè)api很相似,通過(guò)css選擇器來(lái)查找元素,注意選擇器要符合CSS選擇器的規(guī)則

  • 首先來(lái)介紹一下document.querySelector

  • document.querySelector返回第一個(gè)匹配的元素,如果沒(méi)有匹配的元素,則返回null

  • 注意,由于返回的是第一個(gè)匹配的元素,這個(gè)api使用的深度優(yōu)先搜索來(lái)獲取元素

<div>
    <div>
        <span class="test">第三級(jí)的span</span>  
    </div>
</div>
<div class="test">          
    同級(jí)的第二個(gè)div
</div>
<input type="button" id="btnGet" value="獲取test元素" />

document.getElementById("btnGet").addEventListener("click",function(){
    var element = document.querySelector(".test");
    alert(element.textContent);
})
  • 這個(gè)例子很簡(jiǎn)單,就是兩個(gè)class都包含“test”的元素,一個(gè)在文檔樹(shù)的前面,但是它在第三級(jí),另一個(gè)在文檔樹(shù)的后面,但它在第一級(jí),通過(guò)querySelector獲取元素時(shí),它通過(guò)深度優(yōu)先搜索,拿到文檔樹(shù)前面的第三級(jí)的元素

  • document.querySelectorAll的不同之處在于它返回的是所有匹配的元素,而且可以匹配多個(gè)選擇符

<div class="test">
    class為test
</div>
<div id="test">
    id為test
</div>
<input id="btnShow" type="button" value="顯示內(nèi)容" />

document.getElementById("btnShow").addEventListener("click",function(){
    var elements = document.querySelectorAll("#test,.test");    
    for(var i = 0,length = elements.length;i<length;i++){
        alert(elements[i].textContent);
    }   
})
  • 這段代碼通過(guò)querySelectorAll,使用id選擇器和class選擇器選擇了兩個(gè)元素,并依次輸出其內(nèi)容。要注意兩點(diǎn):

    • querySelectorAll也是通過(guò)深度優(yōu)先搜索,搜索的元素順序和選擇器的順序無(wú)關(guān)
    • 返回的是一個(gè)非即時(shí)的NodeList,也就是說(shuō)結(jié)果不會(huì)隨著文檔樹(shù)的變化而變化
  • 兼容性問(wèn)題querySelectorquerySelectorAllie8以下的瀏覽器不支持

  • 小結(jié)

    • document.getElementById返回一個(gè)對(duì)象
    • document.getElementsByNamedocument.getElementsByClasName返回一個(gè)對(duì)象數(shù)組

六、節(jié)點(diǎn)關(guān)系型API


[圖片上傳失敗...(image-1d163c-1545535313683)]

  • html文檔中的每個(gè)節(jié)點(diǎn)之間的關(guān)系都可以看成是家譜關(guān)系,包含父子關(guān)系,兄弟關(guān)系等等

6.1 父關(guān)系型API


  • parentNode:每個(gè)節(jié)點(diǎn)都有一個(gè)parentNode屬性,它表示元素的父節(jié)點(diǎn)。Element的父節(jié)點(diǎn)可能是ElementDocumentDocumentFragment
  • parentElement:返回元素的父元素節(jié)點(diǎn),與parentNode的區(qū)別在于,其父節(jié)點(diǎn)必須是一個(gè)Element,如果不是,則返回null

6.2 兄弟關(guān)系型API


  • previousSibling:節(jié)點(diǎn)的前一個(gè)節(jié)點(diǎn),如果該節(jié)點(diǎn)是第一個(gè)節(jié)點(diǎn),則為null。注意有可能拿到的節(jié)點(diǎn)是文本節(jié)點(diǎn)或注釋節(jié)點(diǎn),與預(yù)期的不符,要進(jìn)行處理一下

  • previousElementSibling:返回前一個(gè)元素節(jié)點(diǎn),前一個(gè)節(jié)點(diǎn)必須是Element,注意IE9以下瀏覽器不支持

  • nextSibling previousSibling 存在兼容性問(wèn)題

  • nextElementSibling previousElementSibling 推薦使用

<script>
    var oUl = document.getElementById('ul1');

    var firstEle = oUl.firstElementChild;
    var lastEle = oUl.lastElementChild;

    firstEle.nextElementSibling.style.background = 'red';
    lastEle.previousElementSibling.style.background = 'green';

</script>

[圖片上傳失敗...(image-2a3be4-1545535313683)]

  • nextSibling:節(jié)點(diǎn)的后一個(gè)節(jié)點(diǎn),如果該節(jié)點(diǎn)是最后一個(gè)節(jié)點(diǎn),則為null。注意有可能拿到的節(jié)點(diǎn)是文本節(jié)點(diǎn),與預(yù)期的不符,要進(jìn)行處理一下
  • nextElementSibling:返回后一個(gè)元素節(jié)點(diǎn),后一個(gè)節(jié)點(diǎn)必須是Element,注意IE9以下瀏覽器不支持

6.3 子關(guān)系型API


  • childNodes
    • 返回一個(gè)即時(shí)的NodeList,表示元素的子節(jié)點(diǎn)列表,子節(jié)點(diǎn)可能會(huì)包含文本節(jié)點(diǎn),注釋節(jié)點(diǎn)等。childNodes子節(jié)點(diǎn)列表集合(只讀屬性 有兼容性問(wèn)題 )
<ul id="ul1">
    <li>11111</li>
    <li>22222</li>
    <li>3333</li>
    <li>44444</li>
</ul>
<script>
    var oUl = document.getElementById('ul1');
    console.log(oUl.childNodes);
</script>

[圖片上傳失敗...(image-560f38-1545535313683)]

  • 從截圖中可以看出 這段代碼中ul的子節(jié)點(diǎn)有9個(gè),這說(shuō)明使用childNodes獲取的節(jié)點(diǎn)包括了文本節(jié)點(diǎn)和元素節(jié)點(diǎn)

  • childNodes 在低版本的ie 瀏覽器下獲取的節(jié)點(diǎn)只包括元素節(jié)點(diǎn),這就導(dǎo)致了兼容性問(wèn)題

  • 如何解決兼容性??

    • 根據(jù)子節(jié)點(diǎn)的nodeType屬性值判斷
for (var i=0; i<oUl.childNodes.length; i++) {

     if ( oUl.childNodes[i].nodeType == 1 ) {
        oUl.childNodes[i].style.background = 'red';
     }

 }
  • children

    • 一個(gè)即時(shí)的HTMLCollection,子節(jié)點(diǎn)都是ElementIE9以下瀏覽器不支持。children子節(jié)點(diǎn)列表集合(只讀屬性 推薦使用 )
  • children 獲取的子節(jié)點(diǎn)只包含元素節(jié)點(diǎn)

for (var i = 0; i<oUl.children.length; i++){
    oUl.children[i].style.background = 'red';
}
  • firstNode:第一個(gè)子節(jié)點(diǎn)

  • lastNode:最后一個(gè)子節(jié)點(diǎn)

  • firstChild (firstElementChild) lastChild(lastElementChild) 第一個(gè)子節(jié)點(diǎn) 最后一個(gè)子節(jié)點(diǎn)

  • firstChildlastChildchildNodes同樣的存在兼容性問(wèn)題,在低版本ie瀏覽器中只能獲取到元素節(jié)點(diǎn)

  • firstElementChildlastElementChild 獲取第一個(gè)元素子節(jié)點(diǎn),最后一個(gè)元素子節(jié)點(diǎn) 推薦使用

var oUl = document.getElementById('ul1');

//    oUl.firstChild.style.background = 'red';//標(biāo)準(zhǔn)瀏覽器 報(bào)錯(cuò)
//    oUl.lastChild.style.background = 'red';//標(biāo)準(zhǔn)瀏覽器 報(bào)錯(cuò)

oUl.firstElementChild.style.background = 'red';
oUl.lastElementChild.style.background = 'red';

[圖片上傳失敗...(image-724b20-1545535313683)]

  • hasChildNodes方法:可以用來(lái)判斷是否包含子節(jié)點(diǎn)

七、元素屬性型


7.1 setAttribute


  • setAttribute:它允許我們對(duì)元素屬性值做出修改與getAttribute一樣setAttribute也能用于元素節(jié)點(diǎn)
  • 通過(guò)setAttribute對(duì)文檔做出修改后,在通過(guò)瀏覽器的查看源碼選項(xiàng)看到的任然是改變之前的屬性值,也就是說(shuō)setAttribue做出的修改,不會(huì)反應(yīng)到文檔本身的源碼里
  • setAttribute優(yōu)勢(shì)在于可以修改文檔中的任何一個(gè)屬性

element.setAttribute(name, value);
  • 其中name是特性名,value是特性值。如果元素不包含該特性,則會(huì)創(chuàng)建該特性并賦值。
  • 如果元素本身包含指定的特性名為屬性,則可以訪問(wèn)屬性進(jìn)行賦值,比如下面兩條代碼是等價(jià)

element.setAttribute("id","test");

element.id = "test";
  • 非DOM的解決方案

    • 其實(shí)不用setAttribute也可以改變?cè)氐膶傩?/li>
    • setAttribute方法是第一級(jí)DOM的組成部分,它可以設(shè)計(jì)任何元素節(jié)點(diǎn)的任意屬性。在第1級(jí)DOM出現(xiàn)之前,你可以通過(guò)另外一種辦法設(shè)置大部分元素的屬性
element.value = "the new value";

與下面語(yǔ)句等價(jià)

element.setAttribute("value","the new value");

7.2 getAttribute


  • getAttribute返回指定的特性名相應(yīng)的特性值,如果不存在,則返回null或空字符串。
  • getAttribute不屬性doucment對(duì)象,不能通過(guò)document對(duì)象調(diào)用,只能通過(guò)元素節(jié)點(diǎn)對(duì)象調(diào)用
  • 例如可以與getElementsByTagName方法合用,獲取每個(gè)ptitle屬性
var paras = document.getElementsByTagName("p");
for(var i=0;i<para.lenght;i++){
    alert(paras.getAttrtitube("title"));
}

八、表格操作


表格操作

九、樣式操作


樣式操作

十、大小和偏移


大小和偏移

十一、網(wǎng)上的一張思維導(dǎo)圖總結(jié)




最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,702評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,143評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 175,553評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,620評(píng)論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,416評(píng)論 6 405
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 54,940評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,024評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,170評(píng)論 0 287
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,709評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,597評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,784評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,291評(píng)論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,029評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,407評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,663評(píng)論 1 280
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,403評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,746評(píng)論 2 370

推薦閱讀更多精彩內(nèi)容