【JS红宝书学习】10DOM

本文详细介绍了DOM(文档对象模型)的概念,包括节点层次、节点类型、节点属性和方法,如appendChild、insertBefore等。同时讲解了Document类型,如获取元素、文档信息和查找元素的方法。此外,还讨论了Element类型,包括获取和设置特性、创建元素以及Text、Comment等特殊类型的节点操作。最后,提到了动态脚本和样式操作以及表格、样式和NodeList在DOM操作中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

DOM描述了一个层次化的节点树,允许开发人员添加、移除、修改页面的一部分。DOM拖泰语Netscape及微软公司创始的DHTML(动态HTML)

1、节点层次

DOM节点分为几种不同的类型,每种类型分别表示文档中不同的信息及标记。每个节点都拥有各自的特点、数据、方法,另外也和其他节点存在某种关系。节点之间的关系构成了层次,而所有页面标记则表现为一个以特定节点为根节点的树形结构。
1、node类型
DOM1定义了一个Node接口,该接口将由DOM中的所有节点类型实现。这个Node接口在JavaScript中是作为Node类型实现的。除了IE之外,在所有浏览器中都可以访问到这个类型。Javascript中所有节点类型都继承自Node类型,因此所有节点类型都共享着相同的基本属性和方法。
每个节点都有一个nodeType类型(比如可以通过someNode.nodeType访问),用于表明节点的类型。共12种,用以下12个数值常量表示。
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

①nodeName和nodeValue属性
如果想了解节点的具体信息,就要使用nodeNamenodeValue两个属性,这两个属性的值完全取决于节点的类型
比如对于元素节点来说nodeName就是元素的标签名

节点关系
childNodes属性
每个节点都有一个childNodes属性,其中保存着一个NodeList对象,但是要注意NodeList对象虽然可以使用方括号语法,也有length属性,但它不是一个Array实例(和arguments类似),同时NodeList对象是一个动态的对象,而不是一个快照,它会随着节点树的变化而变化。访问NodeList对象除了可以使用方括号外,还可以使用item方法,比如childNodes[0]和childNode.item(0)是等价的。如果需要数组切片之类的方法,应使用call方法,比如[].call(childNodes,0)。
parentNode属性
指向文档书中父节点,一个childNodes列表中的所有节点都指向相同的父节点。
每个childNodes列表中的节点,都可以使用previousSiblingnextSibling属性访问同胞节点,如果childNodes只有一个值,那previousSibling和nextSibling会返回null。
父节点的lastChildfirstChild分别指向其childNodes列表中最后一个和第一个节点,如果没有子节点,那么lastChild和firstChild会返回null。
如果想知道有无子节点,应当调用hasChild()方法,比单纯查看childNodes的length要更好用。
ownerDocument
属性
这个属性指向表示整个文档的文档节点。使用这个属性可以让我们不必在节点层次中通过层层回溯退回到根节点,而直接到达根节点。

操作节点:因为关系指针都是只读的,所以DOM提供了一些操作节点的方法。
appenChild()
向父节点添加一个子节点(添加到childNodes的末尾),如果节点本来就在文档中了,那么就将原来的节点换到新的位置。比如,如果将第一个子节点添加,那么第一个子节点变成最后一个。
insertBefore()
调用这个方法会将一个节点添加到另一个节点的同胞层次的前一个,也就是childNodes列表中的前一个。
replaceChild()
替换父节点的子节点,需要两个参数,第一个参数指定要替换的节点,第二个参数指定代替它的节点。尽管被替换掉的节点还在文档中,但在文档中没了自己的位置。
removeChild()
删除一个子节点,比如someNode.removeChild(someNode.lastChild)
cloneNode()
用于创建调用这个方法的节点的一个完全相同的副本。参数是一个布尔值,true则执行深拷贝,false则执行浅拷贝。
normalize()
用于处理文档树中的文本节点。因为解析器或者DOM操作的原因,可能会有文本节点不包含文本,或者接连出现两个文本节点的情况。当在某个节点调用这个方法的时候,就会在该节点的后代节点中查找这两种情况。如果是第一种则删除该文本节点,如果是第二种情况则合并成一个文本节点。

注意Document指一个类型,document特指浏览器中实现的HTMLDocument的一个实例。
2、Document类型
JavaScript通过Document类型表示文档。在浏览器中,document对象是HTMLDocument(继承自Document类型,这样看也可以有XMLDocument)的一个实例,表示整个HTML页面。而且,document对象是window对象的一个属性,因此可以作为全局对象来访问。Document节点具有以下特征:
A、nodeType的值为9
B、nodeName的值为"#document"
C、nodeValue的值为null
D、parentNode的值为null
E、ownerDocument的值为null
F、其子节点可能是一个DocumentType(最多一个)、Element(最多一个)、ProcessingInstruction或Comment

1、文档的子节点
有两个内置的访问子节点的快捷方式,第一个就是documentElement属性,该属性始终指向HTML页面中的html元素。另一个就是通过childNodes列表来访问。同时,document对象还有一个body属性,直接指向body元素,在很多代码中document.body会高频率的出现,这个属性非常常用。还有一个doctype属性,表明文档类型,但由于不同浏览器的支持不同,这个属性不常用。
2、文档信息
document特有的几个属性。
**title:**包含title元素中的文本(就是显示在标题栏或者标签页的那段文本),可以用这个属性在js中设置标题。
**URL:对应地址栏中的包含页面完整的URL
domain: 只包含页面的域名(url后边那段)
referrer: 来源页面的url,有可能是空字符串
URL、domain、referrer实际上就是请求的HTTP头部中的属性,这里js只是提供了接口。三个属性中只有domain是可以修改的,当然一般也不改这个值。
修改domain主要用于两个框架间对象的通信,比如一个框架来源于"www.wrox.com",一个来源于"p2p.wrox.com",由于domain字符串不一样,两个页面就无法互相访问对方的js对象,如果将domain都设置为"wrox.com",那么就打破了这个限制。同时要注意对于domain的修改,如果domain一开始是“松散的loose”(比如是wrox.com),那么就不能改回“紧绷的tight”(比如www.wrox.com)
3、查找元素
getElementById() 要求传入的id与元素中id属性完全相同才返回,包括大小写
getElementsByTagName() 返回一个HTMLCollection对象,与Nodelist对象类似,可以使用item方法和方括号语法来访问。
同时HTMLCollection还提供了
namedItem()*方法,支持按元素的name特性取得集合中的项。
如果希望获取文档中所有的元素,可以向getElementByTagName()方法传入一个通配符

上面两个都是Document对象给定的方法,下面的是HTMLDocument自己的方法
getElementsByName() 返回所有带有给定name特性的元素。但是如果对这个HTMLCollection对象使用namedItem()方法只会返回第一个,因为这个集合中所有的元素的name特性都是相同的。
4、特殊集合
document.anchors 包含文档中所有带name特性的a元素
document.applets 包含文档中所有的applet元素,因为已经不建议使用applet元素了,所以这个集合也不建议使用
document.forms 包含文档中所有的form元素,与document.getElementByTagName(‘form’)得到的结果相同
document.images 包含文档中所有的img元素,与document.getElementByTagName(‘img’)得到的结果相同
document.links 包含文档中所有带href特性的a元素
5、DOM一致性检测
document.implementation.hasFeature(“XML”,“1.0”)返回是否支持DOM功能(XML)和版本号(1.0)
6、文档写入
提供了四个方法,将输出流写入网页中
write()
writeln()
open()
close()

2、Element类型

element对象是常用度仅次于document的对象。Element类型用于表现XML或HTML元素,提供了对元素标签名、子节点及特性的访问。Element节点具有以下特征:
A、nodeType的值为1
B、nodeName的值为元素的标签名
C、nodeValue的值是null
D、parentNode可能是Document或Element
E、子节点可能是Element、Text、Comment、ProcessingInstruction、CDATASection或EntityReference
要访问元素的标签名,可以使用nodeName属性,也可以使用tagName属性,这两个属性会返回相同的值,但是tagName语义性更好。
注意在HTML中,获取的标签名全是大写字母,比如DIV,需要调用toLowerCase()方法,然后再比较。
1、html元素
所有的HTML元素都由HTMLElement类型表示,或者它的子类型表示。HTMLElement类型直接继承自Element并添加了一些属性。添加的这些属性分别对应于每个HTML元素,如下
id:元素在文档中的唯一标识符
titile:有关元素的附加说明信息,一般通过工具提示条显示出来。
lang:元素内容的语言代码,使用较少
dir:语言的方向,值为"ltr(left-to-right)“或"rtl(right-to-left)”,也很少使用
className:与元素的class特性相对应,即为元素指定的css类。没有将这个属性命名为class是因为class是ES的保留字。
2、获取特性
操作DOM的方法主要有三个,分别是
getAttribute()
serAttribute()
removeAttribute()

注意当使用getAttribute()方法时,想要获取class就要直接传入"class",而非className,否则会返回null,因为根本就没有className这个特性。只有在使用对象获取的时候才需要用className当标识。
特性名是不区分大小写的,所以"ID"和“id”表示的是一个特性。根据HTML5规范,如果自定义了一个特性,就要在前面加入data-的前缀以便验证。
由于id和align下HTML中是div元素的公认特性,因此该元素的DOM对象中也将存在对应的属性。
有两类特殊的特性,虽然有对应的属性名,但属性的值与通过getAttribute()返回的并不一致。
第一个就是style特性,返回的style特性是一个文本,而使用属性返回的是一个对象。
第二个是onclick这样的事件处理程序,当在元素上使用时,onclick特性中包含的是JavaScript代码字符串,如果通过属性来访问,则会返回相应代码。这是因为onclick属性本身就应该被赋予一个函数值。
由于这两个特殊的特性,建议选择使用对象的属性,只有在取得自定义特性值的时候,才会使用getAttribute()方法。
3、设置特性
就是使用setAttribute()方法,方法接受两个参数,第一个是特性名,第二个是值。如果特性已经存在,就会以特性的值替换掉现有的值,如果特性不存在,就会创建该属性并设置相应的值。
通过setAttribute方法会自动给对象创建属性,而使用对象的属性不会为元素创建特性。
4、attributes属性
Element类型是唯一一个使用attributes属性的DOM节点类型,attributes属性是一个NamedNodeMap类型的集合,与NodeList类似,也是一个“动态集合”。元素的每一个特性都由一个Attr节点表示,每个节点都保存在NamedNodeMap对象中。NamedNodeMap对象有以下方法:
getNamedItem(name):返回nodeName属性等于name的节点。等同于方括号语法。
removeNamedItem(name):从列表中移除nodeName等于name的节点
setNamedItem(node):向列表中添加节点,以节点的nodeName属性为索引。
item(pos):返回位于数字pos位置处的节点。
比如

var id = element.attributes["id"].nodeValue;
var id = element.attributes.getNamedItem("id").nodeValue;

一般情况下建议使用前面的getAttribute()、setAttribute()、removeAttribute(),除非需要遍历attributes元素的特性:

var attrName = element.attributes[i].nodeName;
var attrName = element.attributes[i].nodeValue;

5、创建元素

var div = document.createElement();
div.id = "myId";
div.className = "box";
document.body.appendChild(div);

或者

var div = document.createElement("<div id = \"myId\" class=\"box\"><\/div>");

在解析时,IE和其他浏览器有着显著的不同,IE会将下方代码解析成3个节点(3个li元素),其他浏览器会解析成7个节点(3个li元素,和4个文本节点,即li元素之间的空白符)

<ul id="myId">
	<li>Item 1</li>
	<li>Item 2</li>
	<li>Item 3</li>
</ul>

如果改成下方的代码,则IE和其他浏览器都会解析成3个节点。

<ul id="myId"><li>Item 1</li><li>Item 2</li><li>Item 3</li></ul>

3、Text类型

文本节点由Text类型标识,包含的是可以照字面解释的纯文本内容。纯文本中可以包含转移后的HTML字符,但不能包含HTML代码。Text节点具有以下特征:
nodeType值为3
nodeName的值为“#text”
nodeValue的值为节点所包含的文本
parentNode是一个Element
没有子节点

可以通过nodeValue属性或者data属性访问Text节点中包含的文本,这两个属性的值是相同的,对nodeValue的修改也会在data中显示出来。
使用下列方法可以操作节点中的文本:
appendData(text):将text添加到节点的末尾
deleteData(offset,count):从offset开始删除count个字符
insertData(offset,text):从offset开始插入text
replaceData(offset,count,text):用text替换从offset指定的位置到offset+count位置的文本
splitText(offset):从offset指定的位置将当前文本节点分成两个文本节点
substringData(offset,count):提取从offset指定的位置泰始到offset+count位置处的字符串
除了上述方法,文本节点还有一个length属性,保存着节点中字符的数目。
注意下面两个的区别,第一个没有文本节点,第二个因为有一个空格所以有文本节点。

<div></div>
<div> </div>

1、创建文本节点
通过document.createTextNode()创建新文本节点,这个方法接受一个参数即要插入节点中的文本。

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

如果再向element添加一个Text节点,则会合并这两个文本的内容变为一个文本节点。

2、规范化文本节点
Node类型定义了一个normalize()方法,对任何类型节点都可以调用这个方法,这个方法会将包含多个文本节点合并成一个节点。

3、分割文本节点
Text类型提供了一个作用与normalize()相反的方法:splitText(),这个方法会接受一个参数,从参数处分割,原来的文本节点包括之前的,新节点包括后面的,并且这两个文本节点的parentNode相同。

5、Comment类型

注释在DOM中是通过Comment类型来表示的,Comment节点具下列特征:
A、nodeType的值为8
B、nodeName的值为“#comment”
C、nodeValue的值是注释的内容
D、parentNode可能是Document或Element
E、不支持子节点
Comment类型与Text类型继承自相同的基类,因此它拥有除了splitText()之外的所有字符串操作方法。与Text类型相似,可以通过nodeValue和data属性来获取注释内容。
注释节点可以从父节点获取,比如

<div><!-- comment --></div>

当然,基本不会有人会利用Comment相关的接口

6、CDATASection

7、DocumentType类型

8、DocumentFragment类型

9、Attr类型

DOM操作技术

1、动态脚本
使用script元素可以向页面中插入JavaScript代码,一种是通过src特性包含外部文件,另一个就是通过这个元素本身来包含代码。
创建动态脚本也有两种方式
第一种,直接加载外部的JavaScript文件,这样会立即运行。

<script type="text/javascript" src="client.js"></script>

第二种,通过DOM代码

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

这样做的好处是,可以如实反映相应的HTML代码,并且在执行最后一步将scipt插入到body内前,都不会下载脚本。
另外就是行内的使用方式,在script标签内部写js代码。
2、动态样式
能够把CSS央视包含到HTML页面中的元素有两个,一个是link元素用于包含外部的文件,一个是style元素用于指定嵌入的样式。

<link rel="stylesheet" type="text/css" href="styles.css">

要注意一定要将link添加到head中

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

使用style元素来包含嵌入式css

<style type="text/css">
body{
	background-color:red;
}
</style>

DOM

var style = document.createElement("style");
style.type = "text/css";
style.appenChild(document.createTextNode("body{background-color:red;}"));
var head = document.getElementsByTagName("head")[0];
head.appendChild(style);

3、操作表格

4、使用NodeList

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值