1. 程式人生 > >(九)JavaScript DOM操作詳解

(九)JavaScript DOM操作詳解

DOM (Document Object Model)
DOM定義了表示和修改文件所需方法。DOM物件即為宿主物件,由瀏覽器廠商定義,用來操作htmlxml功能的一類物件的集合。

節點(node)

DOM 的最小組成單位叫做節點(node)。文件的樹形結構(DOM 樹),就是由各種不同型別的節點組成。每個節點可以看作是文件樹的一片葉子。

節點的型別有七種。

  • Document:整個文件樹的頂層節點
  • DocumentType:doctype標籤(比如<!DOCTYPE html>
  • Element:網頁的各種HTML標籤(比如<body><a>等)
  • Attribute:網頁元素的屬性(比如class="right"
  • Text:標籤之間或標籤包含的文字
  • Comment:註釋
  • DocumentFragment:文件的片段

瀏覽器提供一個原生的節點物件Node,上面這七種節點都繼承了Node,因此具有一些共同的屬性和方法。

節點(node)的一些屬性

Node.prototype.nodeType
nodeType屬性返回一個整數值,表示節點的型別。

  • 文件節點(document):9
  • 文件型別節點(DocumentType):10
  • 元素節點(element):1
  • 屬性節點(attr):2
  • 文字節點(text):3
  • 註釋節點(Comment):8
  • 文件片斷節點(DocumentFragment):11

Node.prototype.nodeName
nodeName

屬性返回節點的名稱

Node.prototype.nodeValue
nodeValue屬性返回當前節點本身的文字值,該屬性可讀寫。 只有文字節點(text)和註釋節點(comment)有文字值

遍歷節點
Node.prototype.parentNode
parentNode 屬性返回當前節點的父節點

Node.prototype.childNodes
childNodes 屬性返回當前節點的所有子節點

Node.prototype.firstChild,Node.prototype.lastChild
firstChild屬性返回第一個子節點lastChild屬性返回最後一個子節點

Node.prototype.previousSibling,Node.prototype.nextSibling
previousSibling

屬性返回前一個兄弟節點nextSibling屬性返回後一個兄弟節點

遍歷元素節點
Node.prototype.parentElement
parentElement 屬性返回當前節點的父元素節點 (IE9以下不相容)

ParentNode.children / Element.children
children 屬性返回當前節點的所有子元素節點

ParentNode.firstElementChild,ParentNode.lastElementChild / Element.firstElementChild,Element.lastElementChild
firstElementChild屬性返回當前節點的第一個子元素節點 (IE9以下不相容)
lastElementChild 屬性返回當前節點的最後一個子元素節點 (IE9以下不相容)

Element.nextElementSibling,Element.previousElementSibling
nextElementSibling 返回前一個兄弟元素節點 (IE9以下不相容)
previousElementSibling 返回後一個兄弟元素節點 (IE9以下不相容)

節點(node)的一些方法

Node.prototype.hasChildNodes()
hasChildNodes方法返回一個布林值,表示當前節點是否有子節點。

插入節點
Node.prototype.appendChild()
appendChild方法接受一個節點物件作為引數,將其作為最後一個子節點,插入當前節點。該方法的返回值就是插入文件的子節點。
如果引數節點是 DOM 已經存在的節點,appendChild方法會將其從原來的位置,移動到新位置。

//新建一個 <p> 節點,將其插入document.body的尾部
var p = document.createElement('p');
document.body.appendChild(p);

Node.prototype.insertBefore()

var insertedNode = parentNode.insertBefore(newNode, referenceNode);

insertBefore方法接受兩個引數,第一個引數是所要插入的節點newNode,第二個引數是父節點parentNode內部的一個子節點referenceNode。newNode將插在referenceNode這個子節點的前面。返回值是插入的新節點newNode。

var p = document.createElement('p');
document.body.insertBefore(p, document.body.firstChild);

上面程式碼中,新建一個<p>節點,插在document.body.firstChild的前面,也就是成為document.body的第一個子節點。
注意,如果所要插入的節點是當前 DOM 現有的節點,則該節點將從原有的位置移除,插入新的位置。

append()、prepend()、before()、after() 這些新的方法存在相容性問題。

ParentNode.append(),ParentNode.prepend()

append方法為當前節點追加一個或多個子節點,位置是最後一個元素子節點的後面。
該方法不僅可以新增元素子節點,還可以新增文字子節點。

var parent = document.body;

// 新增元素子節點
var p = document.createElement('p');
parent.append(p);

// 新增文字子節點
parent.append('Hello');

// 新增多個元素子節點
var p1 = document.createElement('p');
var p2 = document.createElement('p');
parent.append(p1, p2);

// 新增元素子節點和文字子節點
var p = document.createElement('p');
parent.append('Hello', p);

注意,該方法沒有返回值。

prepend方法為當前節點追加一個或多個子節點,位置是第一個元素子節點的前面。它的用法與append方法完全一致,也是沒有返回值。

ChildNode.before(),ChildNode.after()
before方法用於在當前節點的前面,插入一個或多個同級節點。兩者擁有相同的父節點。
注意,該方法不僅可以插入元素節點,還可以插入文字節點。

var div = document.getElementById('myDiv');

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

// 插入元素節點
div.before(p);

// 插入文字節點
div.before('Hello');

// 插入多個元素節點
div.before(p, span);

// 插入元素節點和文字節點
div.before(p, 'Hello');

after方法用於在當前節點的後面,插入一個或多個同級節點,兩者擁有相同的父節點。用法與before方法完全相同。

刪除節點
Node.prototype.removeChild()
removeChild方法接受一個子節點作為引數,用於從當前節點移除該子節點。返回值是移除的子節點。如果引數節點不是當前節點的子節點,removeChild方法將報錯。

var divA = document.getElementById('A');
divA.parentNode.removeChild(divA);

ChildNode.remove()
remove方法,移除當前節點

var p = document.getElementsByTagName('p')[0];
p.remove();

document 節點

document物件繼承了EventTarget介面、Node介面、ParentNode介面。這意味著,這些介面的方法都可以在document物件上呼叫。除此之外,document物件還有很多自己的屬性和方法。

document 節點的一些屬性

document.doctype屬性,指向<DOCTYPE>節點,即文件型別(Document Type Declaration,簡寫DTD)節點。HTML 的文件型別節點,一般寫成<!DOCTYPE html>。如果網頁沒有宣告 DTD,該屬性返回null

document.documentElement屬性返回當前文件的根元素節點(root)。HTML網頁的該屬性,一般是<html>節點。

document.body,document.head
document.body屬性指向<body>節點,document.head屬性指向<head>節點。

document 節點的一些方法

document 獲取 節點的一些方法

document.getElementById()方法返回匹配指定id的元素節點。如果沒有發現匹配的節點,則返回null。

document.getElementsByTagName() 方法返回匹配標籤名的元素節點。返回的是類陣列物件。(最常用

document.getElementsByClassName()方法返回匹配class屬性的元素節點,引數可是多個class屬性。返回的是類陣列物件。(IE8及以下IE版本沒有)

document.getElementsByName() 方法返回匹配name屬性的元素節點。返回的是類陣列物件(舊版本瀏覽器只有部分標籤生效比如表單、img、iframe)

document.querySelector()document.querySelectorAll()
document.querySelector方法接受一個 CSS 選擇器作為引數,返回一個匹配該選擇器的元素節點。document.querySelectorAll方法可返回多個匹配的元素節點,返回的是類陣列物件。(IE7及以下IE版本沒有,缺陷:不是實時資料)

document 建立 節點的一些方法

document.createElement 方法用來生成元素節點,並返回該節點。
createElement 方法的引數為元素的標籤名,即元素節點的tagName屬性

var newDiv = document.createElement('div');

document.createTextNode方法用來生成文字節點(Text例項),並返回該節點。createTextNode方法的引數是文字節點的內容。

//新建一個div節點和一個文字節點,然後將文字節點插入div節點
var newDiv = document.createElement('div');
var newContent = document.createTextNode('Hello');
newDiv.appendChild(newContent);

document.createAttribute方法生成一個新的屬性節點(Attr例項),並返回它。createAttribute方法的引數name,是屬性的名稱。

//為div1節點,插入一個值為 newVal 的 my_attrib 屬性。
var node = document.getElementById('div1');

var a = document.createAttribute('my_attrib');
a.value = 'newVal';
node.setAttributeNode(a);

// 或者直接
node.setAttribute('my_attrib', 'newVal');

Element (元素節點)

Element 元素節點的一些屬性

Element.innerHTML
Element.innerHTML屬性返回一個字串,等同於該元素包含的所有 HTML 程式碼。該屬性可讀寫,常用來設定某個節點的內容。

el.innerHTML = '';

如果將innerHTML屬性設為空,等於刪除所有它包含的所有節點。

注意,讀取屬性值的時候,如果文字節點包含&、小於號(<)和大於號(>),innerHTML屬性會將它們轉為實體形式&amp;&lt;&gt;

Element.innerText(曾經老版本火狐不相容,現在可忽略)
Element.textContent(IE8及以下IE版本不相容)

Element.className,Element.classList
className屬性用來讀寫當前元素節點的class屬性。它的值是一個字串,每個class之間用空格分割。
classList屬性返回一個類似陣列的物件,當前元素節點的每個class就是這個物件的一個成員。

// HTML 程式碼 <div class="one two three" id="myDiv"></div>
var div = document.getElementById('myDiv');

div.className
// "one two three"

div.classList
// {
// 	0 : "one"
// 	1 : "two"
// 	2 : "three"
// 	length : 3
// 	value : "one two three"
// }

classList物件有下列方法。

add():增加一個 class。
remove():移除一個 class。
toggle():將某個 class 移入或移出當前元素。
contains():檢查當前元素是否包含某個 class。
item():返回指定索引位置的 class。
toString():將 class 的列表轉為字串。

//html 程式碼為 <div id="myDiv"></div>

var div = document.getElementById('myDiv');

div.classList.add('myClass');
div.classList.add('foo', 'bar');
div.classList.remove('myClass');
div.classList.toggle('myClass'); // 如果 myCssClass 不存在就加入,否則移除
div.classList.contains('myClass'); // 返回 true 或者 false

//html 程式碼變為 <div id="myDiv" class="foo bar myClass"></div>

Element 元素節點的一些方法

Element.getAttribute()
Element.getAttribute方法返回當前元素節點的指定屬性的值。如果指定屬性不存在,則返回null。

//html 程式碼為 <div class="div-1" data-foo="bar"></div>

var div = document.getElementsByTagName('div')[0];
console.log(div.getAttribute('class'));        //div-1
console.log(div.getAttribute('data-foo'));    //bar
console.log(div.getAttribute('id'));         //null

Element.setAttribute()
Element.setAttribute方法用於為當前元素節點新增屬性。如果同名屬性已存在,則相當於編輯已存在的屬性。該方法沒有返回值。

//html 程式碼為 <div></div>
var div = document.getElementsByTagName('div')[0];
div.setAttribute('id','demo');
//html 程式碼變為 <div id="demo"></div>
Node結構樹,繼承關係的一些問題

在這裡插入圖片描述

獲取元素節點函式的一些注意點
  1. getElementById方法定義在Document.prototype上,即Element節點上不能使用。
  2. getElementsByName方法定義在HTMLDocument.prototype上,即非html中的document(如xml中的document、Element節點)不能使用。
  3. getElementsByTagName方法定義在Document.prototype和Element.prototype上,即HTML、xml中的document和Element節點都能使用,所以getElementsByTagName比較常用。
  4. getElementsByClassName、querySelector、querySelectorAll在Document.prototype和Element.prototype類中均有定義。