JS之DOM

DOM

DOM是文档对象模型(Document Object Model),它是为文文档结构更改和查询提供的一系列API。通过这些API,我们可以对页面进行添加、移动或者更改节点,从而对调整页面结构。1998年,W3C发布了第一级的DOM规范。为基本的文档结构及查询提供了接口。

到目前为止,DOM被分为不同的部分(核心、XML、HTML)和级别(Level 1/2/3)

  • Core DOM
    定义了一套标准的针对任何结构化文档的对象
  • XML Dom
    定义了一套标准的针对XML文档的对象
  • HTML DOM
    定义了一套标准的针对HTML文档的对象

IE中Dom对象都是以CDom的形式实现的,所以和其他浏览器的实现会有一些差异。

节点层次

Dom会将结构性文档描绘成一个由节点形成的文档树。其中,节点又分为多种类型,每种类型代表文档中不同的信息。不同的节点之间的关系行了层次结构,由根节点向下延伸,形成了一棵完整的文档树。

每个文档都有一个根节点,为文档节点(document)。在文档节点之下,一般都会有元素充当文档元素,文档中的所有内容都包含在内。

节点类型

DOM1级定义了一个Node接口,在js中作为Node类型实现,而且js中的所有节点类型都继承至Node类型。

常见的节点类型(及代表等级)有:

  • 元素节点(ELEMENT_NODE 1)
  • 属性节点(ATTRIBUTE_NODE 2)
  • 文本节点(TEXT_NODE 3)
  • 注释节点(COMMENT_NODE 8)
  • 文档类型(DOCUMENT_NODE 9)

判断某节点的节点类型:

1
2
3
if(someNode.nodeType == 1){
console.log(this node is a element);
}

除了nodeType,还可以通过nodeName和nodeValue获得节点信息。

  • 对于元素节点,nodeName就是标签名,nodeValue就是null
  • 对于文本节点,nodeName是“#text”,nodeValue是文本字符串

节点关系

每个节点都有一个childNodes属性,它的值是一个类数组对象NodeList,里面保存了此节点的所有直接子元素。

这个对象也有length属性,但它并不是Array的实例。且它是在Dom结构上动态查询的结果,并不是一直不变的。

访问这个类数组可以用数组的方括号或者item方法。

每个节点拥有访问其他节点的几个属性:

  • parentNode:指向父节点
  • firstNode:指向childNodes列表中第一个子元素
  • lastNode:指向childNodes列表中最后一个子元素
  • previousSibling:指向前一个同胞(同级)元素
  • nextSibling:指向后一个同胞元素
  • ownerDocument:指向文档节点,即document

通过hasChildNodes()方法可以直接知道元素是否有子元素

操作节点

操作子节点的常用方法:

  • appendchild():在节点的childNodes列表末尾插入一个节点,如果该节点已经存在,就会将该节点从原位置移至新位置
  • insertBefore():把节点插入到指定位置,接收两个参数,要插入的节点作为参照的节点,被插入的节点最后会置于同胞参照节点的前面。
  • replaceChild():替换子节点,接收两个参数,要插入的节点要替换的节点,并返回被替换的节点
  • removeChild():移除子节点,将要移除的子节点作为参数,并作为返回值返回。

Document类型

Document类型有一个实例–documnet,它也作为全局对象被挂在window对象上。

document对象作为我们常用的一个对象,弄清楚它的方法属性是非常有必要的:

  • childNodes:既然document也是一个节点,那么他也有所有节点共有的属性
  • documentElement:指向文档中的html元素
  • body:指向文档中的body元素
  • doctype:取得对<!Doctype>的引用
  • title:文档标题
  • url:获取完整的url
  • domain:取得域名(只能设置url中包含的域)
  • referrer:取得来源页面的url

要注意domain,比如在页面中引入了一个框架且页面的域和此框架的域并不相同,那么这时他们是不能通信的,我们可以通过设置domai为相同域来实现通信。设置domain属性只支持从紧绷(mail.qq.com)到松散(qq.com),不支持重新设置为从松散都紧绷。

查找元素

下面是我们常见的集中获得元素索引的方法:

  • getElementById():传入要获取元素的id
  • getElementsByTagName():传入要获取元素的标签名,返回包含零或多个元素的NodesList

    • getElementsByTagName(*)会返回页面所有元素的集合,但在IE中会返回所有注释节点,因为它将注释实现为元素
  • getElementByName():HTMLDocument特有的方法,返回带有name特性的包含所有元素的HTMLCollection,可以通过namedItem()方法(可以在nodesList中获取特定name的项)来获取第一项

Element类型

元素类型(NodeType为1)算是我们最常用到的类型之一了,它提供了我们访问标签名、子节点及其他他行的途径。

它有以下特征:

  • nodeType为1
  • nodeName为标签名,也可用tagName获得
  • nodeValue为null
  • 子节点可能是Element、Text、Comment

HTMLElement类型直接继承与Element类型,我们的所有HTML元素都是HTMLElemnt或者它的子类的实例,这些元素都有一些共有的属性

  • id 唯一标识符
  • title 元素的附加说明,鼠标获取焦点会显示
  • className 类名

获取及设置Attribute

操作特性主要有三个:

  • getAttribute:获取指定特性的value
  • setAttribute:传入设置的特性名及新设置的value
  • removeAttribute:传入要移除的特性名

这些方法其实是在操作一个动态的NamedNodeMap,通过元素的Element.attributes我们可以访问它,我们可以通过操作attributes下的getNamedItem、setNamedItem等方法来实现统一的目的,只不过不是很方便就是了。
一般尽量少用这些方法,而是通过元素的属性直接去获取或者设置特性。

创建元素

通过document.createElement(tagName)方法我们可以创建一个元素,这时元素尚未添加到文档树中,我们通过appendchild()、insertBefore()、replaceChild()来进行插入。

IE下可以直接传入html字符串,如:

1
document.createElement(“<div id=\"nav\">content</div>”)

Text类型

文本节点可以包含转义后的HTML字符,但不能包含HTML代码,文本节点会作为父元素的第一个子元素,所以通过Element.childNodes[0]就可访问。

它有以下特征:

  • nodeType为3
  • nodeName为#text,也可用tagName获得
  • nodeValue为文本
  • 父节点是Element,不支持子节点

操作文本的方法:

  • append():添加文本到末尾
  • deleteData():传入offset(指定的位置),从这里开始删除count个字符
  • insertData():在offset出入文本
  • replace()
  • splitText()

创建文本节点的方法:

document.createTextNode():传入文本内容,最后也需要插入到文档中才能生效

下一篇博客会介绍DOM的一些扩展和DOM2及DOM3的一些新增知识点。