DOM 詳解

DOM

IE中的所有DOM對(duì)象都是以COM對(duì)象的形式實(shí)現(xiàn)的。

節(jié)點(diǎn)層次

DOM可以將任何HTML或XML文檔描繪成一個(gè)由多層節(jié)點(diǎn)構(gòu)成的結(jié)構(gòu)。節(jié)點(diǎn)分為幾種不同的類型:

文檔元素: 在HTML頁面中,文檔元素始終都是<html>元素,(在XML中何元素都可能成為文檔元素)

12種DOM節(jié)點(diǎn)層次(繼承自一個(gè)基類型)

  • 1、node類型
  • 2、Document類型
  • 3、Element類型
  • 4、Text類型
  • 5、Comment類型
  • 6、CDATASection類型(only XML文檔)
  • 7、DocumentType(類型)(在Web瀏覽器中并不常用)
  • 8、DocumentFragment
  • 9、Attr類型
  • ... 其他

一、Node類型(12個(gè)數(shù)值常量來表明節(jié)點(diǎn)的類型。)

DOM1級(jí)定義了一個(gè)Node接口,該接口將由DOM中的所有節(jié)點(diǎn)類型實(shí)現(xiàn)。
JavaScript中的所有節(jié)點(diǎn)類型都繼承自Node類型,因此所有節(jié)點(diǎn)類型都共享著相同的基本屬性和方法。

1、dom.nodeNamenodeValue

這兩個(gè)屬性的值完全取決于節(jié)點(diǎn)的類型,對(duì)于元素節(jié)點(diǎn),node-Name中保存的始終都是元素的標(biāo)簽名,而nodeValue的值則始終為null。

2、節(jié)點(diǎn)的關(guān)系 childNodes 、 parentNode、hasChildNodes()

每個(gè)節(jié)點(diǎn)都有一個(gè)childNodes屬性,其中保存著一個(gè)NodeList對(duì)象,是一種類數(shù)組對(duì)象,用于保存一組有序的節(jié)點(diǎn)。childNodes列表中的每個(gè)節(jié)點(diǎn)相互之間都是同胞節(jié)點(diǎn)。通過使用列表中每個(gè)節(jié)點(diǎn)的previousSiblingnextSibling屬性,可以訪問同一列表中的其他節(jié)點(diǎn)。父節(jié)點(diǎn)與其第一個(gè)和最后一個(gè)子節(jié)點(diǎn)之間也存在特殊關(guān)系。父節(jié)點(diǎn)的firstChildlastChild屬性分別指向其childNodes列表中第一個(gè)和最后一個(gè)節(jié)點(diǎn)。

 ParentNode.lastElementChild
 ParentNode.firstElementChild
3、操作節(jié)點(diǎn)
  • appendChild(): 將一個(gè)節(jié)點(diǎn)添加到指定父節(jié)點(diǎn)的子節(jié)點(diǎn)列表末尾, 如果傳入到appendChild()中的節(jié)點(diǎn)已經(jīng)是文檔的一部分了,那結(jié)果就是將該節(jié)點(diǎn)從原來的位置轉(zhuǎn)移到新位置。即使可以將DOM樹看成是由一系列指針連接起來的,但任何DOM節(jié)點(diǎn)也不能同時(shí)出現(xiàn)在文檔中的多個(gè)位置上。
//將一個(gè)節(jié)點(diǎn)添加到指定父節(jié)點(diǎn)的子節(jié)點(diǎn)列表末尾。
const child = node.appendChild(child);
// node: 是要插入子節(jié)點(diǎn)的父節(jié)點(diǎn).
// child: 即是參數(shù)又是這個(gè)方法的返回值.
  • insertBefore() 參考節(jié)點(diǎn)之前插入一個(gè)節(jié)點(diǎn)作為一個(gè)指定父節(jié)點(diǎn)的子節(jié)點(diǎn)
const insertedElement = parentElement.insertBefore(newElement, referenceElement);
//1. referenceElement為null則newElement將被插入到子節(jié)點(diǎn)的末尾。
//2. 如果newElement已經(jīng)在DOM樹中,newElement首先會(huì)從DOM樹中移除。

insertedElement 是被插入的節(jié)點(diǎn),即 newElement
parentElement 是新插入節(jié)點(diǎn)的父節(jié)點(diǎn)
newElement 是被插入的節(jié)點(diǎn)
referenceElement 在插入newElement之前的那個(gè)節(jié)點(diǎn)

  • replaceChild(): 接受的兩個(gè)參數(shù)是:要插入的節(jié)點(diǎn)和要替換的節(jié)點(diǎn)
replacedNode = parentNode.replaceChild(newChild, oldChild);
// newChild 用來替換 oldChild 的新節(jié)點(diǎn)。如果該節(jié)點(diǎn)已經(jīng)存在于DOM樹中,則它會(huì)被從原始位置刪除。
// oldChild  被替換掉的原始節(jié)點(diǎn)。
// replacedNode 和 oldChild相等。
  • removeChild() 從DOM中刪除一個(gè)子節(jié)點(diǎn)。返回刪除的節(jié)點(diǎn)
let oldChild = node.removeChild(child);
//OR
element.removeChild(child);
// child 是要移除的那個(gè)子節(jié)點(diǎn).
// node 是child的父節(jié)點(diǎn).
// oldChild保存對(duì)刪除的子節(jié)點(diǎn)的引用. oldChild === child.
  • cloneNode(): 接受一個(gè)布爾值參數(shù),表示是否執(zhí)行深復(fù)制。在參數(shù)為true的情況下,執(zhí)行深復(fù)制,也就是復(fù)制節(jié)點(diǎn)及其整個(gè)子節(jié)點(diǎn)樹;在參數(shù)為false的情況下,執(zhí)行淺復(fù)制,即只復(fù)制節(jié)點(diǎn)本身。
  • normalize()

cloneNode 和 normalize 所有類型的節(jié)點(diǎn)都有

二、Document 類型(document對(duì)象-文檔對(duì)象)

JavaScript通過Document類型表示文檔。在瀏覽器中,document對(duì)象繼承自Document類型的一個(gè)實(shí)例,表示整個(gè)HTML頁面,是window對(duì)象的一個(gè)屬性

  • nodeType的值為9;
  • nodeName的值為"#document";
  • nodeValue的值為null;
  • parentNode的值為null;
  • ownerDocument的值為null;

最常見的應(yīng)用還是作為HTMLDocument實(shí)例的document對(duì)象

1、文檔的子節(jié)點(diǎn)

DOM標(biāo)準(zhǔn)規(guī)定Document節(jié)點(diǎn)的子節(jié)點(diǎn)可以是DoumentType、ElementProcessingInstructionComment,但還有兩個(gè)內(nèi)置的訪問其子節(jié)點(diǎn)的快捷方式。

  • documentElement屬性,該屬性始終指向<html>元素。
  • childNodes列表訪問文檔元素,但通過documentElement屬性則能更快捷、更直接地訪問該元素。
// 取得對(duì)<html>的引用
var html = document.documentElement;
// true
alert(html === document.childNodes[0]);
//true
alert(html === document.firstChild);
//取得對(duì)<body>的引用
var body = document.body;
//取得對(duì)<!DOCTYPE>的引用
var doctype = document.doctype;
2、文檔信息

作為HTMLDocument的一個(gè)實(shí)例,document對(duì)象還有一些標(biāo)準(zhǔn)的Document對(duì)象所沒有的屬性。

//取得文檔標(biāo)題
var originalTitle = document.title;
//設(shè)置文檔標(biāo)題
document.title = "New page title";
//取得完整的URL
var url = document.URL;
//取得域名
var domain = document.domain;
//取得來源頁面的URL
var referrer = document.referrer;

只有domain是可以設(shè)置的。但由于安全方面的限制,也并非可以給domain設(shè)置任何值。如果URL中包含一個(gè)子域名,例如p2p.wrox.com,那么就只能將domain設(shè)置為"wrox.com"(URL中包含"www",如www.wrox.com時(shí),也是如此)。不能將這個(gè)屬性設(shè)置為URL中不包含的域,如下面的例子所示。

//假設(shè)頁面來自p2p.wrox.com域
// 成功
document.domain = "wrox.com";
// 出錯(cuò)!
document.domain = "nczonline.net";

當(dāng)頁面中包含來自其他子域的框架或內(nèi)嵌框架時(shí),能夠設(shè)置document.domain就非常方便了。由于跨域安全限制,來自不同子域的頁面無法通過JavaScript通信。而通過將每個(gè)頁面的doc-ument.domain設(shè)置為相同的值,這些頁面就可以互相訪問對(duì)方包含的JavaScript對(duì)象了。

查找元素
  • getElementById()
  • getElementsByTagName()
  • getElementsByName() 只有HTMLDocument類型才有的方法
  • getElementsByClassName() (H5)

classList 屬性
HTML5新增了一種操作類名的方式,可以讓操作更簡(jiǎn)單也更安全,那就是為所有元素添加classList屬性。這個(gè)classList屬性是新集合類型DOMTokenList的實(shí)例。與其他DOM集合類似,DOMTokenList有一個(gè)表示自己包含多少元素的length屬性,而要取得每個(gè)元素可以使用item()方法,也可以使用方括號(hào)語法。此外,這個(gè)新類型還定義如下方法。

  • add(value):將給定的字符串值添加到列表中。如果值已經(jīng)存在,就不添加了。
  • contains(value):表示列表中是否存在給定的值,如果存在則返回true,否則返回false。
  • remove(value):從列表中刪除給定的字符串。
  • toggle(value):如果列表中已經(jīng)存在給定的值,刪除它;如果列表中沒有給定的值,添加它。
特殊集合
  • document.anchors,包含文檔中所有帶name特性的<a>元素;
  • document.forms,包含文檔中所有的<form>元素,與doc-ument.getElementsByTagName("form")得到的結(jié)果相同;
  • document.images,包含文檔中所有的<img>元素,與doc-ument.getElementsByTagName ("img")得到的結(jié)果相同;
  • document.links,包含文檔中所有帶href特性的<a>元素。
文檔寫入

write()、writeln()、open()close()

三、Element 類型

除Document類型之外,Element類型就要算是Web編程中最常用的類型了。Element類型用于表現(xiàn)XML或HTML元素,提供了對(duì)元素標(biāo)簽名、子節(jié)點(diǎn)及特性的訪問。

  • nodeType的值為1;
  • nodeName的值為元素的標(biāo)簽名;
  • nodeValue的值為null;
  • parentNode可能是Document或Element;
  • 其子節(jié)點(diǎn)可能是Element、Text、Comment、Processin-gInstruction、CDATASection或EntityReference
<div id="myDiv"></div>
//可以像下面這樣取得這個(gè)元素及其標(biāo)簽名: 
var div = document.getElementById("myDiv");
//"DIV"
alert(div.tagName);
//true
alert(div.tagName == div.nodeName);
// 在HTML中,標(biāo)簽名始終都以全部大寫表示
1、HTML元素

所有HTML元素都是由HTMLElement或者其更具體的子類型來表示的。

2、操作特性
  • getAttribute()
  • setAttribute()
  • removeAttribute()
3、attributes屬性

attributes屬性中包含一個(gè)NamedNodeMap,與NodeList類似,也是一個(gè)“動(dòng)態(tài)”的集合。元素的每一個(gè)特性都由一個(gè)Attr節(jié)點(diǎn)表示,每個(gè)節(jié)點(diǎn)都保存在NamedNodeMap對(duì)象中。NamedNodeMap對(duì)象擁有下列方法。

4、創(chuàng)建元素

document.createElement()

var div = document.createElement("div");
div.id = "myNewDiv";
div.className = "box";
document.body.appendChild(div);
5、元素的子節(jié)點(diǎn)

元素可以有任意數(shù)目的子節(jié)點(diǎn)和后代節(jié)點(diǎn),因?yàn)樵乜梢允瞧渌氐淖庸?jié)點(diǎn)。元素的childNodes屬性中包含了它的所有子節(jié)點(diǎn),這些子節(jié)點(diǎn)有可能是元素、文本節(jié)點(diǎn)、注釋或處理指令。

四、Text 類型

文本節(jié)點(diǎn)由Text類型表示,包含的是可以照字面解釋的純文本內(nèi)容。純文本中可以包含轉(zhuǎn)義后的HTML字符,但不能包含HTML代碼。

  • nodeType的值為3;
  • nodeName的值為"#text";
  • nodeValue的值為節(jié)點(diǎn)所包含的文本;
  • parentNode是一個(gè)Element;
  • 不支持(沒有)子節(jié)點(diǎn)。

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

  • appendData(text):將text添加到節(jié)點(diǎn)的末尾。
  • deleteData(offset,count):從offset指定的位置開始刪除count個(gè)字符。
  • insertData(offset, text):在offset指定的位置插入text。
  • replaceData(offset, count, text):用text替換從offset指定的位置開始到offset+count為止處的文本。
  • splitText(offset):從offset指定的位置將當(dāng)前文本節(jié)點(diǎn)分成
  • substringData(offset, count):提取從offset指定的位置開始到offset+count為止處的字符串。
  • length屬性,保存著節(jié)點(diǎn)中字符的數(shù)目。
<!-- 沒有內(nèi)容,也就沒有文本節(jié)點(diǎn) -->
<div></div>
<!-- 有空格,因而有一個(gè)文本節(jié)點(diǎn) -->
<div> </div>
<!-- 有內(nèi)容,因而有一個(gè)文本節(jié)點(diǎn) -->
<div>Hello World!</div>

通過 nodeValue 訪問值

1.創(chuàng)建文本節(jié)點(diǎn)
  • document.createTextNode()
var textNode = document.createTextNode("<strong>Hello</strong> world!");

var element = document.createElement("div");
element.className = "message";
var textNode = document.createTextNode("Hello world!");

element.appendChild(textNode);
var anotherTextNode = document.createTextNode("Yippee!"); element.appendChild(anotherTextNode);

document.body.appendChild(element);
2.規(guī)范化文本節(jié)點(diǎn)normalize()。
3.分割文本節(jié)點(diǎn)splitText()。

五、Comment類型

<div id="myDiv"><!--A comment --></div>

DOM操作技術(shù)

動(dòng)態(tài)腳本

var script = document.createElement("script");
script.type = "text/javascript";
script.src = "client.js";
document.body.appendChild(script);

動(dòng)態(tài)樣式

var link = document.createElement("link");
link.rel = "stylesheet";
link.type = "text/css";
link.href = "style.css";
var head = document.getElementsByTagName("head")[0];
head.appendChild(link);

使用NodeList

NodeList每當(dāng)文檔結(jié)構(gòu)發(fā)生變化時(shí),NodeList都會(huì)得到更新。

小結(jié)

DOM由各種節(jié)點(diǎn)構(gòu)成,簡(jiǎn)要總結(jié)如下。

  • 最基本的節(jié)點(diǎn)類型是Node,用于抽象地表示文檔中一個(gè)獨(dú)立的部分;所有其他類型都繼承自Node。
  • Document類型表示整個(gè)文檔,是一組分層節(jié)點(diǎn)的根節(jié)點(diǎn)。在JavaScript中,document對(duì)象是Document的一個(gè)實(shí)例。使用document對(duì)象,有很多種方式可以查詢和取得節(jié)點(diǎn)。
  • Element節(jié)點(diǎn)表示文檔中的所有HTML或XML元素,可以用來操作這些元素的內(nèi)容和特性。
  • 另外還有一些節(jié)點(diǎn)類型,分別表示文本內(nèi)容、注釋、文檔類型、CDATA區(qū)域和文檔片段。

DOM擴(kuò)展

  • querySelector()
  • querySelectorAll()
  • matchesSelector() 這個(gè)方法接收一個(gè)參數(shù),即CSS選擇符,如果調(diào)用元素與該選擇符匹配,返回true;否則,返回false。

H5

一、焦點(diǎn)管理

  • document.activeElement
  • document.hasFocus()

二、HTMLDocument 的變化

  • readyState屬性
document.readyState === 'loading'
document.readyState === 'complete'
  • 字符集屬性
//"UTF-16"
alert(document.charset);
document.charset = "UTF-8";
  • 自定義數(shù)據(jù)屬性
    HTML5規(guī)定可以為元素添加非標(biāo)準(zhǔn)的屬性,但要添加前綴data-,目的是為元素提供與渲染無關(guān)的信息,或者提供語義信息。這些屬性可以任意添加、隨便命名,只要以data-開頭即可。
    dataset屬性來訪問自定義屬性的值。dataset屬性的值是DOMStringMap的一個(gè)實(shí)例,也就是一個(gè)名值對(duì)兒的映射。在這個(gè)映射中,每個(gè)data-name形式的屬性都會(huì)有一個(gè)對(duì)應(yīng)的屬性
//本例中使用的方法僅用于演示
var div = document.getElementById("myDiv");
//取得自定義屬性的值
var appId = div.dataset.appId;
var myName = div.dataset.myname;//設(shè)置值

三、插入標(biāo)記

  • innerHTML屬性
  • outerHTML屬性
  • insertAdjacentHTML()方法

四、內(nèi)存與性能問題

// bad
for (var i=0, len=values.length; i < len; i++){    
//要避免這種頻繁操作??!   
ul.innerHTML += "<li>" + values[i] + "</li>";
}
// good
var itemsHtml = ""; 
for (var i=0, len=values.length; i < len; i++){    
itemsHtml += "<li>" + values[i] + "</li>"; 
}

ul.innerHTML = itemsHtml; 

五、scrollIntoView()

scrollIntoView()可以在所有HTML元素上調(diào)用,通過滾動(dòng)瀏覽器窗口或某個(gè)容器元素,調(diào)用元素就可以出現(xiàn)在視口中。如果給這個(gè)方法傳入true作為參數(shù),或者不傳入任何參數(shù),那么窗口滾動(dòng)之后會(huì)讓調(diào)用元素的頂部與視口頂部盡可能平齊。如果傳入false作為參數(shù),調(diào)用元素會(huì)盡可能全部出現(xiàn)在視口中,(可能的話,調(diào)用元素的底部會(huì)與視口頂部平齊。)不過頂部不一定平齊,例如:

//讓元素可見
document.forms[0].scrollIntoView();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • ??DOM(文檔對(duì)象模型)是針對(duì) HTML 和 XML 文檔的一個(gè) API(應(yīng)用程序編程接口)。 ??DOM 描繪...
    霜天曉閱讀 3,858評(píng)論 0 7
  • ??DOM 1 級(jí)主要定義的是 HTML 和 XML 文檔的底層結(jié)構(gòu)。 ??DOM2 和 DOM3 級(jí)則在這個(gè)結(jié)構(gòu)...
    霜天曉閱讀 1,594評(píng)論 1 3
  • 本章內(nèi)容 理解包含不同層次節(jié)點(diǎn)的 DOM 使用不同的節(jié)點(diǎn)類型 克服瀏覽器兼容性問題及各種陷阱 DOM 是針對(duì) HT...
    悶油瓶小張閱讀 764評(píng)論 0 1
  • 節(jié)點(diǎn)層次 DOM 可以將任何 HTML 和 XML 文檔描繪成一個(gè)由多層節(jié)點(diǎn)構(gòu)成的結(jié)構(gòu)。節(jié)點(diǎn)分為幾種不同的類型,每...
    云之外閱讀 578評(píng)論 0 1
  • 獨(dú)釣云煙閱讀 344評(píng)論 3 11

友情鏈接更多精彩內(nèi)容