JS總結篇--[總結]JS操做DOM經常使用API詳解

文本整理了javascript操做DOM的一些經常使用的api,根據其做用整理成爲建立,修改,查詢等多種類型的api,主要用於複習基礎知識,加深對原生js的認識。javascript

基本概念

在講解操做DOM的api以前,首先咱們來複習一下一些基本概念,這些概念是掌握api的關鍵,必須理解它們。css

Node類型

DOM1級定義了一個Node接口,該接口由DOM中全部節點類型實現。這個Node接口在JS中是做爲Node類型實現的。在IE9如下版本沒法訪問到這個類型,JS中全部節點都繼承自Node類型,都共享着相同的基本屬性和方法。html

每一個節點都有一個nodeType屬性,用於代表節點的類型。節點類型由在Node類型中定義的下列12個數值常量來表示,任何節點類型必居其一:java

Node.ELEMENT_NODE:1
Node.ATTRIBUTE_NODE:2
Node.TEXT_NODE:3
Node.CDATA_SECTION_NODE:4
Node.ENTITY_REFERENCE_NODE:5
Node.ENTITY_NODE:6
Node.PROCESSING_INSTRUCTION_NODE:7
Node.COMMENT_NODE:8
Node.DOCUMENT_NODE:9
Node.DOCUMENT_TYPE_NODE:10
Node.DOCUMENT_FRAGMENT_NODE:11
Node.NOTATION_NODE:12

假設咱們要判斷一個Node是否是元素,咱們能夠這樣判斷:node

if(someNode.nodeType == 1){
    console.log("Node is a element");
}

開發人員最經常使用的就是元素和文本節點。api

這些Node類型中,咱們最經常使用的就是elementtextattributecommentdocumentdocument_fragment這幾種類型。
咱們簡單來介紹一下這幾種類型:瀏覽器

Element類型

Element提供了對元素標籤名,子節點和特性的訪問,咱們經常使用HTML元素好比div,span,a等標籤就是element中的一種。Element有下面幾條特性:
(1)nodeType爲1
(2)nodeName爲元素標籤名,tagName也是返回標籤名
(3)nodeValue爲null
(4)parentNode多是Document或Element
(5)子節點多是Element,Text,Comment,Processing_Instruction,CDATASection或EntityReference緩存

Text類型

Text表示文本節點,它包含的是純文本內容,不能包含html代碼,但能夠包含轉義後的html代碼。Text有下面的特性:
(1)nodeType爲3
(2)nodeName爲#text
(3)nodeValue爲文本內容
(4)parentNode是一個Element
(5)沒有子節點app

Attr類型

Attr類型表示元素的特性,至關於元素的attributes屬性中的節點,它有下面的特性:
(1)nodeType值爲2
(2)nodeName是特性的名稱
(3)nodeValue是特性的值
(4)parentNode爲nulldom

Comment類型

Comment表示HTML文檔中的註釋,它有下面的幾種特徵:
(1)nodeType爲8
(2)nodeName爲#comment
(3)nodeValue爲註釋的內容
(4)parentNode多是Document或Element
(5)沒有子節點

Document

Document表示文檔,在瀏覽器中,document對象是HTMLDocument的一個實例,表示整個頁面,它同時也是window對象的一個屬性。Document有下面的特性:
(1)nodeType爲9
(2)nodeName爲#document
(3)nodeValue爲null
(4)parentNode爲null
(5)子節點多是一個DocumentType或Element

DocumentFragment類型

DocumentFragment是全部節點中惟一一個沒有對應標記的類型,它表示一種輕量級的文檔,可能看成一個臨時的倉庫用來保存可能會添加到文檔中的節點。DocumentFragment有下面的特性:
(1)nodeType爲11
(2)nodeName爲#document-fragment
(3)nodeValue爲null
(4)parentNode爲null

咱們簡單地介紹了幾種常見的Node類型,要記住,HTML中的節點並不僅是包括元素節點,它還包括文本節點,註釋節點等等。在這裏咱們只是簡單地說明了幾種常見的節點,想要進一步學習的同窗能夠查找一下相關資料。

節點建立型api

在這裏,我將經常使用的DOM操做api進行分類,首先要介紹的是建立型的api。這一類型的api,簡而言之就是用來建立節點的。

createElement

createElement經過傳入指定的一個標籤名來建立一個元素,若是傳入的標籤名是一個未知的,則會建立一個自定義的標籤,注意:IE8如下瀏覽器不支持自定義標籤。
使用以下:

var div = document.createElement("div");

使用createElement要注意:經過createElement建立的元素並不屬於html文檔,它只是建立出來,並未添加到html文檔中,要調用appendChild或insertBefore等方法將其添加到HTML文檔樹中。

createTextNode

createTextNode用來建立一個文本節點,用法以下:

var textNode = document.createTextNode("一個TextNode");

createTextNode接收一個參數,這個參數就是文本節點中的文本,和createElement同樣,建立後的文本節點也只是獨立的一個節點,一樣須要appendChild將其添加到HTML文檔樹中。

cloneNode

cloneNode是用來返回調用方法的節點的一個副本,它接收一個bool參數,用來表示是否複製子元素,使用以下:

var parent = document.getElementById("parentElement"); 
var parent2 = parent.cloneNode(true);// 傳入true
parent2.id = "parent2";

這段代碼經過cloneNode複製了一份parent元素,其中cloneNode的參數爲true,表示parent的子節點也被複制,若是傳入false,則表示只複製了parent節點。

咱們看看這個例子:

<div id="parent">
    我是父元素的文本
    <br/>
    <span>
        我是子元素
    </span>
</div>
<button id="btnCopy">複製</button>

var parent = document.getElementById("parent");
document.getElementById("btnCopy").onclick = function(){
    var parent2 = parent.cloneNode(true);
    parent2.id = "parent2";
    document.body.appendChild(parent2);
}

這段代碼很簡單,主要是綁定button事件,事件內容是複製了一個parent,修改其id,而後添加到文檔中。
這裏有幾點要注意:

(1)和createElement同樣,cloneNode建立的節點只是遊離有html文檔外的節點,要調用appendChild方法才能添加到文檔樹中
(2)若是複製的元素有id,則其副本一樣會包含該id,因爲id具備惟一性,因此在複製節點後必需要修改其id
(3)調用接收的bool參數最好傳入,若是不傳入該參數,不一樣瀏覽器對其默認值的處理可能不一樣

除此以外,咱們還有一個須要注意的點:
若是被複制的節點綁定了事件,則副本也會跟着綁定該事件嗎?這裏要分狀況討論:
(1)若是是經過addEventListener或者好比onclick進行綁定事件,則副本節點不會綁定該事件
(2)若是是內聯方式綁定好比:

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

這樣的話,副本節點一樣會觸發事件。

createDocumentFragment

createDocumentFragment方法用來建立一個DocumentFragment。在前面咱們說到DocumentFragment表示一種輕量級的文檔,它的做用主要是存儲臨時的節點用來準備添加到文檔中。
createDocumentFragment方法主要是用於添加大量節點到文檔中時會使用到。假設要循環一組數據,而後建立多個節點添加到文檔中,好比示例:

<ul id="list"></ul>
<input type="button" value="添加多項" 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);
    }
}

這段代碼將按鈕綁定了一個事件,這個事件建立了100個li節點,而後依次將其添加HTML文檔中。這樣作有一個缺點:每次一建立一個新的元素,而後添加到文檔樹中,這個過程會形成瀏覽器的迴流。所謂迴流簡單說就是指元素大小和位置會被從新計算,若是添加的元素太多,會形成性能問題。這個時候,就是使用createDocumentFragment了。
DocumentFragment不是文檔樹的一部分,它是保存在內存中的,因此不會形成迴流問題。咱們修改上面的代碼以下:

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);
}

優化後的代碼主要是建立了一個fragment,每次生成的li節點先添加到fragment,最後一次性添加到list。

建立型API總結

建立型api主要包括createElement,createTextNode,cloneNode和createDocumentFragment四個方法,須要注意下面幾點:
(1)它們建立的節點只是一個孤立的節點,要經過appendChild添加到文檔中
(2)cloneNode要注意若是被複制的節點是否包含子節點以及事件綁定等問題
(3)使用createDocumentFragment來解決添加大量節點時的性能問題

頁面修改型API

前面咱們提到建立型api,它們只是建立節點,並無真正修改到頁面內容,而是要調用appendChild來將其添加到文檔樹中。我在這裏將這類會修改到頁面內容歸爲一類。
修改頁面內容的api主要包括:appendChild,insertBefore,removeChild,replaceChild。

appendChild

appendChild咱們在前面已經用到屢次,就是將指定的節點添加到調用該方法的節點的子元素的末尾。調用方法以下:

parent.appendChild(child);

child節點將會做爲parent節點的最後一個子節點。
appendChild這個方法很簡單,可是還有有一點須要注意:若是被添加的節點是一個頁面中存在的節點,則執行後這個節點將會添加到指定位置,其本來所在的位置將移除該節點,也就是說不會同時存在兩個該節點在頁面上,至關於把這個節點移動到另外一個地方。咱們來看例子:

<div id="child">
    要被添加的節點
</div>
<br/>
<br/>
<br/>
<div id="parent">
    要移動的位置
</div>        
<input id="btnMove" type="button" value="移動節點" />

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

這段代碼主要是獲取頁面上的child節點,而後添加到指定位置,能夠看到本來的child節點被移動到parent中了。
這裏還有一個要注意的點:若是child綁定了事件,被移動時,它依然綁定着該事件。

insertBefore

insertBefore用來添加一個節點到一個參照節點以前,用法以下:

parentNode.insertBefore(newNode,refNode);

parentNode表示新節點被添加後的父節點
newNode表示要添加的節點
refNode表示參照節點,新節點會添加到這個節點以前
咱們來看這個例子:

<div id="parent">
    父節點
    <div id="child">                
        子元素
    </div>
</div>
<input type="button" id="insertNode" value="插入節點" />

var parent = document.getElementById("parent");
var child = document.getElementById("child");
document.getElementById("insertNode").onclick = function(){
    var newNode = document.createElement("div");
    newNode.textContent = "新節點"
    parent.insertBefore(newNode,child);
}

這段代碼建立了一個新節點,而後添加到child節點以前。
和appendChild同樣,若是插入的節點是頁面上的節點,則會移動該節點到指定位置,而且保留其綁定的事件。

關於第二個參數參照節點還有幾個注意的地方:

(1)refNode是必傳的,若是不傳該參數會報錯
(2)若是refNode是undefined或null,則insertBefore會將節點添加到子元素的末尾

removeChild

removeChild顧名思義,就是刪除指定的子節點並返回,用法以下:

var deletedChild = parent.removeChild(node);

deletedChild指向被刪除節點的引用,它等於node,被刪除的節點仍然存在於內存中,能夠對其進行下一步操做。
注意:若是被刪除的節點不是其子節點,則程序將會報錯。咱們能夠經過下面的方式來確保能夠刪除:

if(node.parentNode){
    node.parentNode.removeChild(node);
}

經過節點本身獲取節點的父節點,而後將自身刪除。

replaceChild

replaceChild用於使用一個節點替換另外一個節點,用法以下:

parent.replaceChild(newChild,oldChild);

newChild是替換的節點,能夠是新的節點,也能夠是頁面上的節點,若是是頁面上的節點,則其將被轉移到新的位置
oldChild是被替換的節點

頁面修改型API總結

頁面修改型api主要是這四個接口,要注意幾個特色:
(1)不論是新增仍是替換節點,若是新增或替換的節點是本來存在頁面上的,則其原來位置的節點將被移除,也就是說同一個節點不能存在於頁面的多個位置
(2)節點自己綁定的事件會不會消失,會一直保留着。

節點查詢型API

節點查詢型API也是很是經常使用的api,下面咱們分別說明一下每個api的使用。

document.getElementById

這個接口很簡單,根據元素id返回元素,返回值是Element類型,若是不存在該元素,則返回null。
使用這個接口有幾點要注意:
(1)元素的Id是大小寫敏感的,必定要寫對元素的id
(2)HTML文檔中可能存在多個id相同的元素,則返回第一個元素
(3)只從文檔中進行搜索元素,若是建立了一個元素並指定id,但並無添加到文檔中,則這個元素是不會被查找到的

document.getElementsByTagName

這個接口根據元素標籤名獲取元素,返回一個即時的HTMLCollection類型,什麼是即時的HTMLCollection類型呢?咱們來看看這個示例:

<div>div1</div>
<div>div2</div>
        
<input type="button" value="顯示數量" 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);
}

這段代碼中有兩個按鈕,一個按鈕是顯示HTMLCollection元素的個數,另外一個按鈕能夠新增一個div標籤到文檔中。前面提到HTMLCollcetion元素是即時的表示該集合是隨時變化的,也就是是文檔中有幾個div,它會隨時進行變化,當咱們新增一個div後,再訪問HTMLCollection時,就會包含這個新增的div。

使用document.getElementsByTagName這個方法有幾點要注意:

(1)若是要對HTMLCollection集合進行循環操做,最好將其長度緩存起來,由於每次循環都會去計算長度,暫時緩存起來能夠提升效率
(2)若是沒有存在指定的標籤,該接口返回的不是null,而是一個空的HTMLCollection
(3)「*」表示全部標籤

document.getElementsByName

getElementsByName主要是經過指定的name屬性來獲取元素,它返回一個即時的NodeList對象。
使用這個接口主要要注意幾點:

(1)返回對象是一個即時的NodeList,它是隨時變化的
(2)在HTML元素中,並非全部元素都有name屬性,好比div是沒有name屬性的,可是若是強制設置div的name屬性,它也是能夠被查找到的
(3)在IE中,若是id設置成某個值,而後傳入getElementsByName的參數值和id值同樣,則這個元素是會被找到的,因此最好很差設置一樣的值給id和name

document.getElementsByClassName

這個API是根據元素的class返回一個即時的HTMLCollection,用法以下:

var elements = document.getElementsByClassName(names);

這個接口有下面幾點要注意:

(1)返回結果是一個即時的HTMLCollection,會隨時根據文檔結構變化
(2)IE9如下瀏覽器不支持
(3)若是要獲取2個以上classname,可傳入多個classname,每一個用空格相隔,例如:

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

document.querySelector和document.querySelectorAll

這兩個api很類似,經過css選擇器來查找元素,注意選擇器要符合CSS選擇器的規則。
首先來介紹一下document.querySelector。
document.querySelector返回第一個匹配的元素,若是沒有匹配的元素,則返回null。
注意,因爲返回的是第一個匹配的元素,這個api使用的深度優先搜索來獲取元素。咱們來看這個例子:

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

document.getElementById("btnGet").addEventListener("click",function(){
    var element = document.querySelector(".test");
    alert(element.textContent);
})

這個例子很簡單,就是兩個class都包含「test」的元素,一個在文檔樹的前面,可是它在第三級,另外一個在文檔樹的後面,但它在第一級,經過querySelector獲取元素時,它經過深度優先搜索,拿到文檔樹前面的第三級的元素。

document.querySelectorAll的不一樣之處在於它返回的是全部匹配的元素,並且能夠匹配多個選擇符,咱們來看看下面這個例子:

<div class="test">
    class爲test
</div>
<div id="test">
    id爲test
</div>
<input id="btnShow" type="button" value="顯示內容" />

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);
    }    
})

這段代碼經過querySelectorAll,使用id選擇器和class選擇器選擇了兩個元素,並依次輸出其內容。要注意兩點:

(1)querySelectorAll也是經過深度優先搜索,搜索的元素順序和選擇器的順序無關
(2)返回的是一個非即時的NodeList,也就是說結果不會隨着文檔樹的變化而變化

兼容性問題:querySelector和querySelectorAll在ie8如下的瀏覽器不支持。

節點關係型api

在html文檔中的每一個節點之間的關係均可以當作是家譜關係,包含父子關係,兄弟關係等等,下面咱們依次來看看每一種關係。

父關係型api

parentNode:每一個節點都有一個parentNode屬性,它表示元素的父節點。Element的父節點多是Element,Document或DocumentFragment。

parentElement:返回元素的父元素節點,與parentNode的區別在於,其父節點必須是一個Element,若是不是,則返回null

兄弟關係型api

previousSibling:節點的前一個節點,若是該節點是第一個節點,則爲null。注意有可能拿到的節點是文本節點或註釋節點,與預期的不符,要進行處理一下。

previousElementSibling:返回前一個元素節點,前一個節點必須是Element,注意IE9如下瀏覽器不支持。

nextSibling:節點的後一個節點,若是該節點是最後一個節點,則爲null。注意有可能拿到的節點是文本節點,與預期的不符,要進行處理一下。

nextElementSibling:返回後一個元素節點,後一個節點必須是Element,注意IE9如下瀏覽器不支持。

子關係型api

childNodes:返回一個即時的NodeList,表示元素的子節點列表,子節點可能會包含文本節點,註釋節點等。
children:一個即時的HTMLCollection,子節點都是Element,IE9如下瀏覽器不支持。
firstChild:第一個子節點。
lastChild:最後一個子節點。
hasChildNodes方法:能夠用來判斷是否包含子節點。

元素屬性型api

setAttribute

setAttribute:根據名稱和值修改元素的特性,用法以下:

element.setAttribute(name, value);

其中name是特性名,value是特性值。若是元素不包含該特性,則會建立該特性並賦值。
若是元素自己包含指定的特性名爲屬性,則能夠世界訪問屬性進行賦值,好比下面兩條代碼是等價的:

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

element.id = "test";

getAttribute

getAttribute返回指定的特性名相應的特性值,若是不存在,則返回null或空字符串。用法以下:

var value = element.getAttribute("id");

元素樣式型api

直接修改元素的樣式

elem.style.color = 'red';
elem.style.setProperty('font-size', '16px');
elem.style.removeProperty('color');

動態添加樣式規則

var style = document.createElement('style');
style.innerHTML = 'body{color:red} #top:hover{background-color: red;color: white;}';
document.head.appendChild(style);

window.getComputedStyle

經過element.sytle.xxx只能獲取到內聯樣式,藉助window.getComputedStyle能夠獲取應用到元素上的全部樣式,IE8或更低版本不支持此方法。

var style = window.getComputedStyle(element[, pseudoElt]);

element是要獲取的元素,pseudoElt指定一個僞元素進行匹配。
返回的style是一個CSSStyleDeclaration對象。
經過style能夠訪問到元素計算後的樣式

getBoundingClientRect

getBoundingClientRect用來返回元素的大小以及相對於瀏覽器可視窗口的位置,兼容性很是好(IE6+),用法以下:

var clientRect = element.getBoundingClientRect();

clientRect是一個DOMRect對象,包含left,top,right,bottom,它是相對於可視窗口的距離,滾動位置發生改變時,它們的值是會發生變化的。除了IE9如下瀏覽器,還包含元素的height和width等數據,具體可查看連接

參考

轉載地址:http://luopq.com/2015/11/30/j...
參考地址:http://blog.liuxianan.com/jav...

相關文章
相關標籤/搜索