详解一下DOM(文档对象模型)中的知识点之节点层次(一)

210 阅读5分钟

DOM是文档对象模型,是针对HTML和XML的一个API,DOM描绘了一个层次化的节点树,类似于JavaScript对象,允许开发人员进行增删改查页面的一部分,DOM源于DynamicHTML,也就是DOM0

从今天开始,系统性的学习一下DOM,从节点层次开始,首先重点:DOM所有的节点都是继承自Node类型的,所以12种类型都有相同的属性和方法。

节点是文档的组成单元,节点有12种类型,分别代表着文档中不同的信息及标记,每个节点类型都有各自的特点、数据和方法,也与某些节点类型存在关系。

在HTML中,<html>元素,是文档中的唯一一个文档元素,文档元素是文档的最外层元素,文档中的其他所有元素都包含在文档元素中,在XML中,文档元素可以是任何元素,但是一个文档中只能有一个文档元素,DOM结构中最外层的是Document。

Node类型

DOM1级别定义了一个Node接口,接口将由DOM中所有的节点类型实现,这个Node接口在JS中作为Node类型实现的,除了IE(因为IE8即以下版本并不支持DOM,而是COM),每个节点都有一个nodeType属性,用于表明节点类型:

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.PROCESSION_INSTRUCTION(7)
Node.COMMENT_NODE(8)
Node.DOCUMENT_NODE(9)
Node.DOCUMENT_TYPE_NODE(10)
Node.DOCUMENT_FRAGMENT_NODE(11)
Node.NOTATION_NODE(12)

el:someNode.nodeType == Node.ELEMENT_NODE(IE并不支持,会报错)|1(全部支持)

nodeName和nodeValue属性

要了解节点的具体内容,可以使用nodeName和nodeValue属性,这两个属性完全取决于即诶安的类型。对于元素节点,即nodeType==1,nodeName保存的始终是元素的标签名,nodeValue值始终是null。

1.节点关系

每个节点都有一个childNodes属性,其中保存着一个NodeList对象,NodeList对象是一种类数组对象,可以通过位置来访问这些节点(someNode.childNodes[0]),此对象具有length属性,NodeList对象的独特之处在于他是基于DOM结构动态执行查询的结构,DOM结构的变化会自动放映到NodeList对象中,也就是常说的,NodeList是具有声明的、有呼吸的对象。

NodeList对象不仅可以通过[]去访问其中元素,也可以通过对象特有的item()方法去访问,结果是一样的,只不过开发人员比较习惯使用[]而已。NodeList的length属性并不是定值,它代表着当下时间NodeList的长度,还可以使用

Array.prototype.slice.call(someNode.childNodes,0);

来将NodeList类型转变为数组类型。

每个节点都有一个parentNode属性,该属性指向的是文档树中的父节点。包含在childNodes列表中的所有节点都有一个相同的parentNode,对于同胞节点或称为兄弟节点,可以通过使用列表中每个节点的previousSibling和nextSibling属性,可以访问同一个列表中的其他节点,其中第一个节点的previousSibling值为null,最后一个节点的nextSibling值为null。父节点的firstChild和lastChild分别指向第一个节点和最后一个节点,只有一个子节点的情况下firstChild和lastChild指向同一个节点,如果不存在节点,两属性值都是null。 hasChildNode()方法返回一个boolean值,如果节点存在子节点的话,返回为true,反之返回false,这是比查询someNode.length更加简单的方法,虽然所有的节点都是继承自Node类型,但是并不是所有的节点都可以有子节点。

2.操作节点

因为前面说的关系指针都是只读性的,所以DOM提供了一些操作节点的方法,其中最常用的是appendChild()用于向Node的childNodes列表中末尾添加一个节点,并且该方法执行后返回新增的节点,如果传入的节点是已经存在于childNodes中的节点,会将已有节点移动到末尾位置,一个DOM节点不可以同时出现在文档中的多个位置上。

如果要将节点放在NodeList中的其他位置,需要使用insertBefore()方法,接受两个参数,第一个是需要插入的节点,后一个是需要参照的节点,两个参数都是Node类型的,如果参照节点是null,则insertBefore()和appendChild()执行相同的操作。

replaceChild()接受两个参数,一个是要插入的节点,一个是要替换的节点,实现将要替换的节点删除,并将要插入的节点放在删除节点的位置上。使用此方法插入节点时,要替换的节点的所有关系指针全部复制到新节点上,其实被替换的节点依然存在,但他在文档中已经没有了自己的位置。

删除的方法是removeChild(),接受的参数为node类型,移除之后的节点类似于被替换的节点,依然存在,但是文档树中没有了自己的位置。

其他方法

有两个方法是所有类型都有的,cloneNode()用于创建调用这个方法的节点的一个完全相同的节点,只接受一个参数,boolean类型,表示是否执行深复制,也就是复制节点以及节点的子节点树。复制后返回的节点副本属于文档所有,但并没有给他指定父节点和位置,这个方法并不会复制节点上的js属性,例如事件处理程序等。这个方法只复制特性和子节点。IE存在一个bug,即此方法可以复制事件处理程序,所以最好在复制之前将待复制节点的js属性移除。

normalize()方法的唯一作用就是处理文档树中的文本节点,当在某个节点上调用时,就会在该节点的后代节点查找不包含文本和连续出现两个文本的节点,如果找到了空文本节点,则会删除它,如果发现了两个相邻的文本节点,则将他们合并为一个文本节点。

本章主要讲解了DOM节点层次中的Node类型,请有疑问和建议的小伙伴们及时评论。谢谢大家🙏