亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

快速了解JavaScript的DOM模型

 

概述

DOM全稱Document Object Model,即文檔對(duì)象模型。是html和XML文檔的編程接口,DOM將文檔(HTML或XML)描繪成一個(gè)多節(jié)點(diǎn)構(gòu)成的結(jié)構(gòu)。使用JAVAScript可以改變文檔的結(jié)構(gòu)、樣式和內(nèi)容。

W3C DOM由以下三部分組成:

  • 核心DOM - 針對(duì)任何結(jié)構(gòu)化文檔的標(biāo)準(zhǔn)模型。
  • XML DOM - 針對(duì)XML文檔的標(biāo)準(zhǔn)模型。
  • HTML DOM - 針對(duì)HTML文檔的標(biāo)準(zhǔn)模型。

分類

DOM目前有三種級(jí)別:

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

節(jié)點(diǎn)樹

以下面的HTML為例:

<html>
<head>
    <meta charset="UTF-8">
    <title>節(jié)點(diǎn)樹</title>
</head>
<body>
    <div>測試塊</div>
    <a href="/about">鏈接</a>
</body>
</html>

瀏覽器會(huì)將HTML文檔解析成節(jié)點(diǎn)并組成節(jié)點(diǎn)樹。

快速了解JavaScript的DOM模型

 

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

節(jié)點(diǎn)類型

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

  • Node:瀏覽器提供的原生節(jié)點(diǎn),下面的節(jié)點(diǎn)都繼承它。
  • Document:整個(gè)文檔樹的頂層節(jié)點(diǎn)
  • DocumentType:doctype標(biāo)簽(比如<!DOCTYPE html>)。
  • Element:網(wǎng)頁的各種HTML標(biāo)簽(比如<body>、<a>等)。
  • Attr:網(wǎng)頁元素的屬性(比如class="right")。
  • Text:標(biāo)簽之間或標(biāo)簽包含的文本。
  • Comment:注釋。
  • CDATASection:CDATA區(qū)域,與Comment類型類似。
  • DocumentFragment:文檔的片段。

Node

DOM1中定義了一個(gè)Node接口,JavaScript中所有節(jié)點(diǎn)類型都繼承自Node類型,因此屬性和方法都相同。

在Node類型中定義了nodeType屬性來表明節(jié)點(diǎn)的類型,由12個(gè)常量表示。任何節(jié)點(diǎn)必居其一:

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

使用nodeType可以很容易確定節(jié)點(diǎn)類型,IE中沒有公開Node類型的構(gòu)造函數(shù),使用Node.ELEMENT_NODE比較會(huì)導(dǎo)致錯(cuò)誤。為了兼容IE,可以使用數(shù)值進(jìn)行比較:

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返回節(jié)點(diǎn)的標(biāo)簽名

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

nodeValue返回字符串,表示節(jié)點(diǎn)的文本值,可讀寫。

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

節(jié)點(diǎn)關(guān)系

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

Node中提供了幾種節(jié)點(diǎn)遍歷的屬性:parentNode、childNodes、firstNode/lastNode、
previousSibling/nextSibling、ownerDocument。

Document

JavaScript通過Document類型表示文檔。瀏覽器中的document對(duì)象是HTMLDocument的一個(gè)實(shí)例,表示整個(gè)HTML頁面。Document節(jié)點(diǎn)具有以下特征:

  • nodeType為Node.DOCUMENT_NODE,值為9。
  • nodeName的值為#document。
  • nodeValue的值為null。
  • parentNode的值為null。
  • ownerDocument的值為null。
  • 其子結(jié)點(diǎn)可能是一個(gè)DocumentType、Element、ProcessingInstruction或Comment。

document對(duì)象還有一些屬性來表示網(wǎng)頁的一些信息:

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

URL與domain屬性是相互關(guān)聯(lián)的。

Element

Element類型用于表現(xiàn)XML或HTML元素,提供對(duì)元素標(biāo)簽名、子節(jié)點(diǎn)及特性的訪問。例如<body>和<div>等。Element節(jié)點(diǎn)具有以下特征:

  • nodeType為Node.ELEMENT_NODE,值為1。
  • nodeName的值為元素的標(biāo)簽名。
  • nodeValue的值為null。
  • parentNode可能是Document或Element。
  • 其子節(jié)點(diǎn)可能是Element、Text、Comment、ProcessingInstruction、CDATASection或EntityReference。

要訪問元素的標(biāo)簽名,可以使用nodeName屬性,也可以使用tagName屬性;這兩個(gè)屬性會(huì)返回相同值。

獲取<div id="divId"></div>的標(biāo)簽名:

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

特性和屬性

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

一個(gè)元素中的id等是標(biāo)準(zhǔn)的特性,但也有非標(biāo)準(zhǔn)的特性不能使用div.id方式獲取。那么要用什么方法來訪問非特性。

DOM主要提供了幾個(gè)方法用于對(duì)任何特性進(jìn)行操作,分別是:

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

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

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

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

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

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

attributes屬性

Element類型的attributes屬性返回該元素所有屬性節(jié)點(diǎn)的一個(gè)集合,該集合是一個(gè)"動(dòng)態(tài)"的NamedNodeMap對(duì)象。NamedNodeMap對(duì)象擁有下列方法。

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

attributes屬性包含一系列節(jié)點(diǎn),在節(jié)點(diǎn)中節(jié)點(diǎn)名稱-nodeName 節(jié)點(diǎn)值-nodeValue。

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

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

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

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

element.attributes.setNamedItem(newAttr);

一般情況下getAttribute()、removeAttribute()和setAttribute()方法就夠使用了,但想要遍歷元素的特性,attributes屬性倒是比較方便。下面展示如果迭代元素中每一個(gè)特性并將它們以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是一個(gè)字符串,修改后要設(shè)置整個(gè)字符串的值。

HTML5擴(kuò)展了classList屬性實(shí)現(xiàn)類名的操作。該屬性返回DOMTokenList集合。定義了幾個(gè)方法:

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

Attr

Attr類型在DOM表示元素特性。特性是位于元素attributes屬性中的節(jié)點(diǎn)。具有下列特征:

  • nodeType為Node.TEXT_NODE,值為3。
  • nodeName的值是特性的名稱。
  • nodeValue的值是特性的名稱。
  • parentNode的值為null。
  • 在HTML中不支持子節(jié)點(diǎn)(沒有子節(jié)點(diǎn))。
  • 在XML中子節(jié)點(diǎn)可以是Text或EntityReference。

特性節(jié)點(diǎn)不被認(rèn)為是DOM文檔樹的一部分。最常使用getAttrubute()、setAttribute()和removeAttribute()方法,很少直接引用特性節(jié)點(diǎn)。

Attr對(duì)象有3個(gè)屬性:

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

如果要為元素添加特性,可以使用document.createAttribute(localName)方法,創(chuàng)建名為localName的特性節(jié)點(diǎn)。例如,要為元素添加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

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

  • nodeType為Node.TEXT_NODE,值為3。
  • nodeName的值為#text。
  • nodeValue的值為節(jié)點(diǎn)所包含的文本。
  • parentNode是一個(gè)Element。
  • 不支持子節(jié)點(diǎn)(沒有子節(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)分成兩個(gè)文本節(jié)點(diǎn)。
  • substringData(offset, count):提取從offset指定的位置開始到offset+count為止處的字符串。

除了這些方法外,文本節(jié)點(diǎn)還有一個(gè)length屬性,保存著節(jié)點(diǎn)中字符的數(shù)目。而且,nodeValue.length和data.length中也保存著同樣的值。

修改文本節(jié)點(diǎn)的結(jié)果會(huì)立即得到反映。因此字符串會(huì)經(jīng)過HTML(或XML,取決于文檔類型)編碼。

使用document.createTextNode()可以創(chuàng)建文本節(jié)點(diǎn),在DOM創(chuàng)建中會(huì)講述它。

Comment

注釋在DOM中是通過Comment類型來表示的。Comment節(jié)點(diǎn)具有下列特征:

  • nodeType為Node.COMMENT_NODE,數(shù)值為8。
  • nodeName的值為#comment。
  • nodeValue的值是注釋的內(nèi)容。
  • parentNode可能是Document或Element。
  • 不支持子節(jié)點(diǎn)(沒有子節(jié)點(diǎn))。

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

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

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

如果想創(chuàng)建注釋節(jié)點(diǎn),可以使用document.createComment(data)方法創(chuàng)建。

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

瀏覽器不會(huì)識(shí)別位于</html>標(biāo)簽后面的注釋。一定保證訪問的注釋節(jié)點(diǎn)位于<html></html>之間。

CDATASection

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

  • nodeType為CDATA_SECTION_NODE,值為4。
  • nodeName的值為#cdata-section。
  • nodeValue的值是CDATA區(qū)域中的內(nèi)容。
  • parentNode可能是Document或Element。
  • 不支持子節(jié)點(diǎn)(沒有子節(jié)點(diǎn))。

CDATA區(qū)域只會(huì)出現(xiàn)在XML文檔中,因此多數(shù)瀏覽器都會(huì)把CDATA區(qū)域錯(cuò)誤地解析為Comment或Element。以下面的代碼為例:

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

這個(gè)例子中的<div>元素應(yīng)該包含一個(gè)CDATASection節(jié)點(diǎn)。可是,四大主流瀏覽器無一能夠這樣解析它。即使對(duì)于有效的XHTML頁面,瀏覽器也沒有正確地支持嵌入的CDATA區(qū)域。

在真正的XML文檔中,可以使用
document.createCDataSection()來創(chuàng)建CDATA區(qū)域,只需為其傳入節(jié)點(diǎn)的內(nèi)容即可。

DocumentType

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

  • nodeType為Node.DOCUMENT_TYPE_NODE,值為10。
  • nodeName的值為doctype的名稱。
  • nodeValue的值為null。
  • parentNode是Document類型。
  • 沒有子節(jié)點(diǎn)。

DOM 1級(jí)規(guī)定的DocumentType對(duì)象不能動(dòng)態(tài)創(chuàng)建,只通過解析文檔代碼的方式來創(chuàng)建。支持DocumentType的瀏覽器會(huì)把它保存在document.doctype中。

DocumentType對(duì)象在DOM 1級(jí)中有3個(gè)屬性:

  • DocumentType.name,文檔類型的名稱。
  • DocumentType.entities,文檔類型描述的實(shí)體NamedNodeMap對(duì)象。
  • DocumentType.notations,文檔類型描述的符號(hào)NamedNodeMap對(duì)象。

瀏覽器中一般是HTML或XHTML類型的文檔。所以entities和notations都是空列表。只有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是文檔片段,一種"輕量級(jí)"文檔,可以包含和控制節(jié)點(diǎn),但不像完整文檔那樣占用額外資源。可以將它作為"倉庫"使用。具有下列特征:

  • nodeType為Node.DOCUMENT_FRAGMENT_NODE,值為11。
  • nodeName的值為#document-fragment。
  • nodeValue的值為null。
  • parentNode的值為null。
  • 子節(jié)點(diǎn)可以是Element、ProcessingInstruction、Comment、Text、CDATASection或EntityReference。

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

var fragment = document.createDocumentFragment();

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

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

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

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查找

現(xiàn)在有一段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>
...

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

id選擇器

getElementById(elementId: string): HTMLElement | null;

該方法返回匹配指定id屬性的元素節(jié)點(diǎn),如果不存在,則返回null。

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

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

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

標(biāo)簽選擇器

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

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

let inputs = document.getElementsByTagName('input');
console.log(inputs);    /* HTMLCollection(4) [input, input, input, input, input-name: input, email: input]*/
快速了解JavaScript的DOM模型

 

這個(gè)對(duì)象可以使用length屬性獲取元素?cái)?shù)量,使用數(shù)組語法或item()方法來訪問HTMLCollection對(duì)象中的項(xiàng)。

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

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

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

也可以使用方括號(hào)語法來訪問:

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);
快速了解JavaScript的DOM模型

 

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

類選擇器

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

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

// 獲取所有class中同時(shí)包含'red'和'test'的元素
var classes = document.getElementsByClassName("container");
console.log(classes);
快速了解JavaScript的DOM模型

 

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

Selectors API

W3C發(fā)起指定的標(biāo)準(zhǔn),可使瀏覽器支持CSS查詢。Selectors API的核心是兩個(gè)方法:querySelector()和querySelectorAll()。兼容的瀏覽器中通過Document及Element節(jié)點(diǎn)類型的實(shí)例進(jìn)行調(diào)用。

querySelector()方法

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

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

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

Document和Element都可以調(diào)用querySelector()方法,只是Document會(huì)在文檔元素的范圍內(nèi)查找匹配的元素;Element只會(huì)在該元素后代元素的范圍內(nèi)查找匹配的元素。

querySelectorAll()方法

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

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

// 獲取id為"primary-form"中所有<p>元素
document.getElementById("primary-form").querySelectorAll("p");
// 獲取類為"container"的所有元素
document.querySelectorAll(".container");
// 獲取所有<form>元素中的所有<p>元素
document.querySelectorAll("form p");
快速了解JavaScript的DOM模型

 

matches()方法

Selectors API Level 2規(guī)范為Element類型新增了一個(gè)方法:

matches(selectors: string): boolean;

該方法判斷當(dāng)前DOM節(jié)點(diǎn)是否能完全匹配指定選擇符,如果匹配成功,返回true;匹配失敗,返回false。

var elems = document.getElementsByTagName('p');
for (var i = 0; i < elems.length; i++) {
    // 獲取匹配'container'類選擇符的dom節(jié)點(diǎn) 
    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*/

注意,有些供應(yīng)商會(huì)有自己實(shí)驗(yàn)性方法在matchesSelector()方法之前加些前綴。如果想使用這種方法,可以編寫一個(gè)包裝函數(shù)。

function matchesSelector(element, selector){
    if (element.matches) {
        // 標(biāo)準(zhǔn)方法
        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")){
    //執(zhí)行操作
}

當(dāng)有的瀏覽器不支持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節(jié)點(diǎn)提供了幾種屬性,用于訪問DOM節(jié)點(diǎn)。

parentNode

node.parentNode屬性用于返回指定節(jié)點(diǎn)的父節(jié)點(diǎn)。除document外,所有節(jié)點(diǎn)都有父節(jié)點(diǎn),document對(duì)象的父節(jié)點(diǎn)為null。示例如下:

document.getElementById('divId2').parentNode;

childNodes

node.childNodes屬性用于返回指定節(jié)點(diǎn)的子結(jié)點(diǎn)的Node對(duì)象集合。示例如下:

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

firstChild/lastChild

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

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

previousSibling/nextSibling

node.previousSibling屬性用于訪問之前的同級(jí)節(jié)點(diǎn);node.nextSibling屬性用于訪問之后的同級(jí)節(jié)點(diǎn)。具有相同父節(jié)點(diǎn)為同級(jí)節(jié)點(diǎn),之前或之后表示它們在文檔中出現(xiàn)的順序。實(shí)例如下:

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

ownerDocument

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

document.getElementById('divId2').ownerDocument;

Element Traversal

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

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

支持的瀏覽器為DOM元素添加了這些屬性,利用這些元素不必?fù)?dān)心空白文檔節(jié)點(diǎn),從而可以更方便地查找DOM元素。

DOM操作

因?yàn)殛P(guān)系節(jié)點(diǎn)都是只讀的,所以DOM提供了一些操作節(jié)點(diǎn)的方法。

appendChild()

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

var returnedNode = div.appendChild(newNode);

insertBefore()

node.insertBefore(newChild, refChild)方法會(huì)在指定的參照節(jié)點(diǎn)refChild之前插入新節(jié)點(diǎn)newChild。插入節(jié)點(diǎn)后,被插入的節(jié)點(diǎn)會(huì)變成參照節(jié)點(diǎn)的前一個(gè)同胞節(jié)點(diǎn)(previousSibling),同時(shí)被方法返回。如果refChild是null,則insertBefore()與appendChild()執(zhí)行相同的操作。

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

replaceChild()

node.replaceChild(newChild, oldChild)方法將要替換的節(jié)點(diǎn)oldChild移除,并將要插入的節(jié)點(diǎn)newChild插入并占據(jù)其位置。實(shí)例如下:

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

在使用replaceChild()插入一個(gè)節(jié)點(diǎn)時(shí),該節(jié)點(diǎn)的所有關(guān)系指針都會(huì)從被它替換的節(jié)點(diǎn)復(fù)制過來。被替換的節(jié)點(diǎn)仍然還在文檔中,但它在文檔中已經(jīng)沒有自己的位置了。

removeChild()

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

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

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

上面介紹的四種方法操作的都是某個(gè)節(jié)點(diǎn)的子節(jié)點(diǎn),要使用這幾個(gè)方法必須先取得父節(jié)點(diǎn)。另外,并不是所有類型的節(jié)點(diǎn)都有子節(jié)點(diǎn),如果在不支持子節(jié)點(diǎn)的節(jié)點(diǎn)上調(diào)用這些方法,將會(huì)導(dǎo)致錯(cuò)誤發(fā)生。

DOM創(chuàng)建

DOM節(jié)點(diǎn)創(chuàng)建最常用的便是document.createElement()和document.createTextNode()方法。

createElement()

document.createElement(tagName)方法根據(jù)指定tagName標(biāo)簽名創(chuàng)建新元素節(jié)點(diǎn),返回一個(gè)HTMLElement對(duì)象。標(biāo)簽名在HTML文檔中不區(qū)分大小寫,在XML(包括XHTML)文檔中區(qū)分大小寫。例如,創(chuàng)建一個(gè)<p>元素。

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

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

createTextNode()

document.createTextNode(data: string)方法根據(jù)指定data文本創(chuàng)建新文本節(jié)點(diǎn)。作為參數(shù)的文本按照HTML或XML的格式進(jìn)行編碼。

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

在創(chuàng)建新文本節(jié)點(diǎn)的同時(shí),也會(huì)為其設(shè)置ownerDocument屬性。

cloneNode()

node.cloneNode(deep)方法用于對(duì)調(diào)用這個(gè)方法的節(jié)點(diǎn)創(chuàng)建一個(gè)完全相同的副本。deep是布爾值,設(shè)置是否執(zhí)行深復(fù)制。默認(rèn)為false,執(zhí)行淺復(fù)制(只復(fù)制節(jié)點(diǎn)本身);當(dāng)為true時(shí),執(zhí)行深復(fù)制(復(fù)制節(jié)點(diǎn)及其整個(gè)子節(jié)點(diǎn)樹)。

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

這些用于創(chuàng)建節(jié)點(diǎn)和復(fù)制節(jié)點(diǎn)的方法,創(chuàng)建或復(fù)制的節(jié)點(diǎn)并不會(huì)出現(xiàn)在文檔中,需要通過appendChild()、insertBefore()或replaceChild()將它添加到文檔中。

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

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

一旦將節(jié)點(diǎn)添加到文檔樹中,瀏覽器就會(huì)立即呈現(xiàn)。

一旦使用appendChild()等方法插入相鄰的同胞文本節(jié)點(diǎn)時(shí),會(huì)導(dǎo)致相鄰文本節(jié)點(diǎn)混亂。

而在一個(gè)包含兩個(gè)或多個(gè)文本節(jié)點(diǎn)的父元素上調(diào)用normalize()方法,就會(huì)將所有文本節(jié)點(diǎn)合并成一個(gè)節(jié)點(diǎn)。

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!"

瀏覽器在解析文檔時(shí)永遠(yuǎn)不會(huì)創(chuàng)建相鄰的文本節(jié)點(diǎn)。這種情況只會(huì)作為執(zhí)行DOM操作的結(jié)果出現(xiàn)。

還有一個(gè)與normalize()相反的方法splitText(offset):將一個(gè)文本節(jié)點(diǎn)分成兩個(gè)文本節(jié)點(diǎn)。

var element = document.createElement("div");
element.className = "message";
var textNode = document.createTextNode("Hello, Pandora!");
element.appendChild(textNode);
document.body.appendChild(element);
var newNode = element.firstChild.splitText(6);
console.log(element.firstChild.nodeValue);  // "Hello,"
console.log(newNode.nodeValue);  // " Pandora!"
console.log(element.childNodes.length);  // 2

分享到:
標(biāo)簽:模型 DOM
用戶無頭像

網(wǎng)友整理

注冊時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評(píng)定2018-06-03

通用課目體育訓(xùn)練成績評(píng)定