DOM(文档对象模型)是针对HTML和XML文档的一个API(应用程序编程接口)。DOM描绘了一个层次化的节点树,允许开发人员添加、移除和修改页面的某一部分。
10.1节点层次
文档节点是每个文档的根节点。文档节点只有一个根节点,即<html>元素。总共有12种节点类型。
10.1.1Node类型
JS中所有节点类型都继承自Node类型,因此所有节点类型都共享着相同的基本属性和方法。
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)
If(someNode.nodeType == 1){
alert(‘node is an element’)
}
1. nodeName和nodeValue属性
使用前先检测一下节点的类型
if(someNode.nodeType==1){
// 使用
}
2. 节点关系
每个节点都有一个childNodes属性,其中保存着一个NodeList对象。NodeList是一种类数组对象,用于保存一组有序的节点,可以通过位置来访问这些节点。虽然可以通过方括号语法来访问NodeList的值,而且这个对象也有length属性,但它比你更不是Array的实例。Nodelist对象的独特之处在于,它实际上是基于DOM结构动态执行查询的结果,因此DOM结构的变化能够自动反应在NodeList对象中。NodeList是有生命、有呼吸的对象,而不是我们第一次访问它们的某个瞬间拍摄下来的一张快照。
访问保存在NodeList中的节点可以通过方括号或者使用item()方法
let firstChild = someNode.childNodes[0]
let secondChild = someNode.childNodes.item(1)
let count = someNode.childNodes.length
childNodes
parentNode
若无值均为null
firstChild
lastChild
previousSibling
nextSibling
3. 操作节点
末尾添加,方法返回添加的节点
let returnNode = someNode.appendChild(newNode)
returnNode == newNode // true
someNode.lastChild == newNode // true
如果传入到appendChild中的节点已经是文档的一部分,那结果就是该节点从原来的位置转移到新位置。即使可以将DOM树看成是由一系列指针连接起来的,但任何DOM节点都不能同时出现在文档中的多个位置上。
Let returnNode = someNode.appendChild(someNode.firstChild)
returnNode == someNode.firstChild // false
returnNoce == someNode.lastChild // true
插入,方法返回插入的节点
let returnNode = someNode.insertBefore(插入的节点,参照的节点)
returnNode = newNode
若参照节点为null执行结果跟appendChild一样
取代,要替换的节点由这个方法返回并从文档树中被移除,同时由要插入的节点占据其位置。尽管从技术上中,被替换的节点仍然还在文档中,但他在文档中已经没有了自己的位置。
let returnNode = someNode.replaceChild(插入的节点,要替换的节点)
移除,方法返回被移除的节点
someNode.removeChild(要移除的节点)
4. 其他方法
所有类型的节点都有的
cloneNode(boolean)
true 深复制,复制节点及其整个子节点树
false 浅复制,只复制节点本身。
复制返回的节点副本属于文档,但是没有为它指定父节点,因此这个克隆的副本就成了一个孤儿。需要通过appenChild(),insertBefore(),replaceChild()将他添加到文档中
<ul>
<li>1</li>
<li>2</li>
<ul>
ul元素的引用已经存在变量mylist中了
Let deepList = mylist.clone(true)
deepList.length // 3
let shallowList = mylist.clone(false)
shallowList.length // 0
normalize() 处理文档树中的文本节点
由于解析器的实现或DOM操作等原因,可能会出现文本节点不包含文本,或者接连出现两个文本节点的情况。当在某个节点调用normalize(),就会在该节点的后代节点中查找上述两种情况,删除空文本节点,合并相邻的文本节点。
10.1.2 Document类型
JS通过Document类型表示文档。在浏览器中,document对象是HTMLDocument(继承自Document类型)的一个实例,表示整个HTML页面。而且,document对象也是window对象的一个属性,因此可以将其作为全局对象来访问。Document节点具有以下特征
nodeType=9
nodeName='#document'
nodeVlaue=null
parentNode=null
ownerDocument=null
其子节点可能是一个DocumentType(最多一个)、Element(最多一个)、ProcessingInstruction或Coment
最常见的应用是作为HTMLDocument实例的document对象
通过这个文档对象,不仅可以取得与页面有关的信息,而且还能操作页面的外观及其底层结构
1. 文档的子节点
document.documentElement // 取得<html>的引用,html是document的唯一子节点
document.body // 取得对<body>的引用
document.doctype // 取得对<!DOCTYPE>的引用
2. 文档信息
document.title // 标题,可以设置
document.URL // 完整URL,即地址栏中的URL
document.domain // 域名,可以设置,一开始是松散则不能将它在设为紧绷的,否则导致错误
document.referrer // 来源页面的URL
3. 查找元素
document.getElementById() // <input><textarea></textarea><button></button><select></select>的name特性不要与其他元素ID相同
document.getElementsByTagName() // 参数为元素标签名如'img',返回HTMLCollection对象,与NodeList非常类似
let images=document.getElementsByTagName('img')
images[0]、images.item(0)
HTMLCollection对象还有一个方法namedItem()
<img src="" name="myImage">
let myImage=images.namedItem('myImage')
document.getElementsByTagName("*") // 取得文档中所有元素,在IE中将返回所有注释节点
document.getElementsByName(name) // 返回给定name特性的所有元素,NodeList
4. 特殊集合
document.anchors // 文档中所有带name特性的<a>元素
document.links // 文档中所有带href特性的<a>元素
document.form = document.getElementsByTagName('form')
document.images = document.getElementsByTagName('img')
5. DOM一致性检测
6. 文档写入
将输出流写入到网页的能力,主要体现在write()、writeln()、open()、close()
write()、writeln()接受一个字符串参数,即要写入到输出流中的文本
write()原样写入,writeln()末尾添加一个换行字符(\n),页面被加载的过程中,可以使用者两个方法向页面中动态的加入内容。
document.write('<strong>'+ (new Date()).toString + '</strong>')
如果在文档加载结束再调用会重写页面
window.onload=function(){
document.write('<strong>'+ (new Date()).toString + '</strong>')
}
open()、close()分别用户打开和关闭网页的输出流。如果是在页面加载期间使用write()、writeln(),则不需要用到这两个方法
10.1.3Element类型
Element类型用于表现XML或HTML元素,提供了对元素标签名、子节点及特性的访问。
nodeType=1
nodeName=元素的标签名
nodeVlaue=null
parentNode=Document或者Element
其子节点可能是Element、Text、Comment、ProcessingInstruction、CDATASection或EntityReference
要访问元素的标签名,可以使用nodeName属性,也可以使用tagName属性(更清晰),返回相同的值。
标签名始终都以全部大写
1. HTML元素
所有的HTML元素都由HTMLElement类型表示,不是直接通过这个类型,也是通过它的子类型来表示。
HTMLElement元素直接继承自Element并添加了一些属性
id 唯一标识
title 有关元素的附加说明,一般根据工具提示条显示出来
className,与元素的class特性对应,即为元素指定的CSS类。
lang 元素内容的语言代码,很少使用
dir 语言的方向,值为ltr(left-to-right)或rtl,很少使用
并不是所有属性的修改都会在页面中直观的显示出来。对id和lang的修改是透明的,对title的修改只有移动到这个元素上才出来,对dir的修改会在被重写的那一刻,对className的修改如果关联了与之前不同的样式则会马上应用。
2. 取得特性
每个元素都由一个或多个特性,这些特性的用途是给出相应元素或其内容的附加信息。
getAttribute() 若不存在返回null
setAttribute()
removeAttribute()
可以针对任何特性使用,包括HTMLElement类型属性的形式定义的特性。
div.getAttribute(“id”)
div.getAttribute(“class”) className只有通过对象属性访问特性采用
也可以取得自定义特性
特性的名称不区分大小写
HTML5规范,自定义特性应该加上data-前缀以便认证
两类通过属性的值和getAttribute()返回的值并不相同
- Style
通过getAttribute()访问的style特性值返回的是css文本
通过属性来访问则是一个对象
- onclick这样的事件处理程序
通过getAttribute()访问返回相应代码的字符串
通过属性返回js代码
建议操作dom使用特性通过使用对象属性的方法
取自定义特性值才使用getAttribute()
3. 设置特性
setAttribute(attributeName,value)
如果存在就替换,不存在就创建
通过这种方法设置的特性名会被统一转换为小写
如果给DOM元素添加一个自定义属性,该销魂哥不会自动成为元素的特性。
div.myColor=”red”
div.getAttribute(‘myColor’) //null