Node 类型
所有节点类型都继承于 Node 类型,因此所有节点类型都共享这相同的基本属性和方法。
基本属性和方法
- nodeName :节点名。对于元素类型,则是元素的标签名(均为大写),如"SPAN"、"DIV";对于其他类型会有不同的值,下面每个类型会分别指出。
- nodeValue :节点值。对于元素类型为
null
;对于其他类型会有不同的值,下面每个类型会分别指出。
- hasChildNodes() :布尔值,是否含有子节点。
- childNodes :NodeList 对象的集合,是一个类数组,实际是基于 DOM 结构动态查询的结果。
- firstChild :等效于 childNodes[0] ;
- lastChild :等效于 childNodes[childNodes.length - 1] 。
- parentNode :指向父节点。
- previousSibling :前一个同胞节点;
- nextSibling :后一个同胞节点。
- ownerDocument :指向节点所在的整个文档节点。
下面 4 个是比较常用的方法,但必须是含有子节点或能有子节点的节点对象才能使用:
- appendChild(newNode) :向 childNodes 集合的末尾添加一个新节点。
- removeChild(node) :移除指定的子节点,并返回被移除的节点。
- repalceChild(newNode, node) :用新节点替换原子节点,返回被替换的原节点。
- insertBefore(newNode, node) :在参照子节点(可为
null
)后添加新节点,返回新节点。
下面 2 个方法是所有节点都能使用:
- clone(isDeepClone?) :克隆当前节点,可以接收一个参数:是否深克隆,深克隆表示包含其所有子节点,否则只复制节点本身。
- normalize() :移除空的文本节点,并连接相邻的文本节点。
还有一个属性,用于表示节点的类型:
- nodeType :常量值,一共有 12 种,如 "Node.ELEMENT_NODE" 或 数字 1 ,下面每个类型会分别给出对象的值。
节点比较的方法
用于比较两个节点,如div1.isSameNode(div2)
,返回结果为布尔值。以下有两个概念:相同,表示两个对象指向的是同一个 DOM 节点对象;相等,表示两个对象的类型、属性、内容等均相同,但不一定是同一个对象。
- isSameNode(node) :判断与 node 对象是否相同,document 对象可用。
- isEqualNode(node) :判断与 node 对象是否相等,document 对象不可用。
Document 类型
document 类型表示文档。在浏览器中,document 对象是 HTMLDocument (继承自 Document 类型) 的一个实例,表示整个 HTML 页面。且 document 对象 是 window 对象 的一个属性。
特征:
- nodeType:Node.DOCUMENT_NODE(9)
- nodeName:"#document"
- nodeValue:
null
- parentNode:
null
- ownerDocument:
null
- childNodes:可能是 DocumentType(最多一个)、Element(最多一个)、ProcessingInstruction、Comment 。
一般属性
- documentElement :指向文档中的<html>元素。
- body :指向文档中的<body>元素。
- doctype :指向文档中的<!DOCTYPE>元素。
- title :指向文档中的<title>元素。
- URL :文档的 完整 URL 。
- domain :文档 URL 的主机名。
获取元素的方法
- getElementById() :获取指定 ID 的元素,不存在这返回
null
。 - getElementsByTagName() :获取给定标签名的所有元素的集合,返回 HTMLCollection 对象,该对象是一个类数组,找不到指定标签则集合为空。
- getElementsByClassName() :获取给定 CSS 类名的所有元素的集合,返回 HTMLCollection 对象。
- getElementsByName() :获取给定 name 特性的所有元素的集合,返回 NodeList 。
- querySelector() :获取给定 CSS 选择符的第一个元素,无则返回null。
- querySelectorAll() :获取给定 CSS 选择符的所有元素的集合,返回 NodeList 。
特殊集合
获取的集合都是 HTMLCollection 对象。
- anchors:包含所有待 name 特性的<a>元素
- forms:包含所有<form>元素
- images:包含所有<img>元素
- links:包含所有带有 href 特性的<link>元素
焦点管理
HTML5 新增了 1 个属性和 1 个方法用于辅助管理 DOM 的焦点。
- activeElement :引用 DOM 中当前获得焦点的元素。
- hasFocus() :当前文档是否获得了焦点,布尔值。用于确认用户是否与页面在交互。
HTML5 扩展的 HTMLDocument 属性:
- readyState :文档加载情况,值有两种,加载中(loading)、加载完成(complete)。
- compatMode :渲染模式,值有两种,标准(CSS1Compat)、混集(BackCompat)。
- head :指向文档中的<head>元素。
字符集属性
- chartset :文档使用的字符集,如 "UTF-8"。
专有扩展
以下属性方法并未写入标准,并非所有浏览器都支持,使用前请检测是否存在。
- children:与 childNodes 类似。返回的是一个 HTMLCollection 实例,只包含元素中同样还是元素的子节点,除此外和 childNodes 无差别。
- contains(node) :检测 node 元素是否为本元素的后代节点,返回布尔值。注意,以自身作为参数,结果也是 true 。
- innerText :可读写。读模式,由浅入深的顺序将子文档树的所有文本拼接起来;写模式,删除所有子节点,插入指定的文本节点。
Element 类型
Element
是非常通用的基类,所有Document
对象下的对象都继承它。以下内容主要针对 HTMLElement
类型(HTML文档)。
特征
- nodeType: Node.ELEMENT_NODE(1)
- nodeName: 元素的标签名(与 tagName 的值相同)
- nodeValue: null
- parentNode: Document 或 Element
- childNodes:可能是 Element、Text、Comment、ProcessingInstruction、CDATASection、EntityReference 。
标准特性
以下是 HTML 元素都存在的标准特性,属性值均为可读写。标准特性可以作为对象的属性直接访问,而自定义特性需要用特定方法获取/修改。
- id: 元素在文档的唯一标识符
- title:有关元素的附加说明信息,一般通过工具提示条显示出来
- lang:元素内容的语言代码,很少使用
- dir:语言的方向,值为"ltr"(左到右)或"rtl"(右到左),很少使用
- className:元素的 CSS 类名
获取/操作特性的方法
上面提到标准特性,以下 3 个方法可以访问对象的所有特性(包括标准与自定义特性)。举个例,对于<div class="myDiv" my-prop="myProp"></div>
来说,class
就是标准特性,my-prop
就是自定义特性。下面方法的第一个参数为特性名。
- getAttribute() :获取特性。
- setAttribute() :修改特性,需要第二个参数:新的特性值。若特性不存在,则为其添加新特性并赋值
- removeAttribute() :移除特性。
特殊特性
特殊特性也可以作为对象的属性直接访问,但与标准特性有点不同,属性访问的值与使用方法getAttribute()
得到的值并不一致。
- style 特性
-
.style
:得到一个 CSSStyleDeclaration 对象,该对象包含所有能设置的内联样式。更多关于样式请点击链接。 .getAttribute('style')
:返回style特性的字符串值,如"width: 571px;"
,未设置任何值则返回null
。
.onclick
:得到一个事件处理的 JavaScript 函数,如未指定则返回null
。.getAttribute('onclick')
:返回事件处理函数的字符串值,如未指定则返回null
。- 顺带一说,
.click()
可以触发该元素的单击事件,其他事件同理。
attributes 属性
attributes 属性只能被 Element 类型使用,指向 NamedNodeMap 对象,是类似与 NodeList 的"动态"集合,包含该元素的每个特性,每个特性都由一个 Attr 节点表示 (下面介绍) 。
- NamedNodeMap 对象的方法:
- attributes.getNamedItem(name):获取指定特性节点。
- attributes.setNamedItem(name, value):添加或设置特性节点。
- attributes.removeNamedItem(name):移除指定特性节点。
- attributes.getNamedItem(name):获取指定特性节点。
- 属性值访问:
如,attributes['class']
,和
attributes.getNamedItem('class')
等效。
创建元素
使用document.createElement(tagName)
方法创建并返回该新元素,tagName 在 html 文档中不区分大小写,然后通过上面的属性或方法为其添加特性,最后通过appendChild()
等方法插入到文档树中。
Selectors API Level 2 规范新增的一个方法
matchesSelector()
:接收一个 CSS 选择符为参数,返回布尔值,表示是否该选择符是否与调用元素匹配。如,document.body.matchesSelector('body.page1'); // true
。
Element Traversal API 添加的 5 个属性
一般情况下,使用 childNodes 和 firstChild 等属性时,获得的值是包含回车/空格/注释的节点,例如<div> <span>content</span> </div>
中,div
对象的 firstChild 是一个空格。为了是筛除掉这种文本/注释节点,所以有了以下属性。值得注意的是,除了最后两个指向同辈元素的属性,Document 类型的也包含前三个属性。
- childElementCount :返回子元素(不包括文本节点和注释)的个数。
- firstElementChild :(非文本和注释节点的)第一个子元素。
- lastElementChild :(非文本和注释节点的)最后一个子元素。
- previousElementSibling :(非文本和注释节点的)前一个同辈元素。
- nextElementSibling :(非文本和注释节点的)后一个同辈元素。
classList 属性
由于可以对一个 Element 对象添加多个 className ,但多个 className 却只是用空格隔开,但我们一般只想修该一个或部分,操作整个 className 字符串显得比较麻烦。所以有了 classList 属性,它是新集合类型 DOMTokenList 的实例,同样是类数组,可以通过方括号语法访问项。classList 对象包含如下属性和方法:
- length :该集合的长度,即类名的个数。
- add(<string>) :将给定的字符串添加到列表中,存在则不添加。
- contains(<string>) :判断集合是否存在给定的值,存在则返回 true ,反之 false 。
- remove(<string>) :从集合中删除给定的字符串。
- toggle(<string>) :开关,即给定的字符串存在则删除,否则添加。
自定义数据属性
HTML5 规定可以为元素添加非标准的属性,但要添加前缀 "data-",目的是为元素提供与渲染无关的信息,或提供语义信息。
例如,<div id="div1" data-appId="123" data-myname="lisi"><div>
。
添加属性后,可以通过元素的 "dataset" 属性访问自定义属性的值。dataset 属性指向 DOMStringMap 的实例,就是一个键值对的映射。
如上述例子中,可以通过document.getElementById('div1').dataset.appid
访问或改写(注意,"appid" 会被转成小写;若标签内是"data-app-id",则 JavaScript 访问其值时,会被转化成驼峰式,即"appId";JavaScript 获取其的数据值类型必定是字符串)。)。
插入标记
使用插入标记的技术,可以直接插入 HTML 字符串。以下是 2 个属性,均为可读写,和 1 个方法。需要注意的是,使用这些属性方法替换子节点可能会导致浏览器的内存占用问题,主要是事件绑定和频繁添加导致,所以建议先手工删除要被替换的元素的所有事件处理程序和循环添加添加 HTML 标记时应处理好所有的字符串再一次过插入到指定位置。
- innerHTML :读模式下,返回与调用元素的所有子节点(包括元素、文本和注释节点)对应的 HTML 标记;写模式下,则指定相对于的字符串量。注意,通过此属性插入到 <script>元素并不会执行其中的代码。不支持此属性的元素有:<col>、<colgroup>、<frameset>、<head>、<html>、<style>、<table>、<tbody>、<thead>、<tfoot>、<tr>。
- outerHTML :与 innerHTML 类似,此属性还包含自身元素标签。例如,某div元素调用 outerHTML ,获取的是
"<div>......</div>"
。 - insertAdjacentHTML(location, HtmlText) :此方法用于在指定位置插入 HTML 文本。location 表示要插入的位置,值必须是以下之一(均为小写):
- "beforebegin":在当前元素之前插入一个紧邻的同辈元素;
- "afterbegin":在当前元素之下的起始位置插入一个新的子元素;
- "beforeend":在当前元素之下的起始位置插入一个新的子元素;
- "afterend":在当前元素之后插入一个紧邻的同辈元素。
scrollIntoView() 方法
当容器内容很多,则需要使用滚动条显示,而此方法是为了更好的控制页面滚动。元素对象调用此方法时,会使元素出项在最外层的带滚动条的元素中,下面用"视口元素"指代"最外层的带滚动条的元素"。可以接收一个布尔值为参数,不传默认为 true 。
- true :默认值,表示元素顶部尽可能与视口元素顶部平齐。
- false :表示元素底部尽可能与视口元素底部平齐。
专有扩展方法(滚动)
这三个方法都只是在 safari 和 chrome 浏览器(可能更多,目前Firefox不支持)部署了。都是与滚动相关。
- scrollIntoViewIfNeeded(isAlignCenter) :当元素已经在视口中,不作任何操作;当元素不在视口中,使滚动窗口滚动到元素可见位置。可传入一个布尔值,isAlignCenter 表示元素是否垂直居中对其。
- scrollByLines(lineCount) :将元素的内容滚动指定的行高,lineCount 可正可负。
- scrollByPages(pageCount) :将元素的内容滚动到指定的页面高度,具体的高度有元素的高度决定。
表单元素
表单元素由<form>
表示,对应的是HTMLFormElement
类型,继承自HTMLElement
。这里不多介绍,请点击链接查看另一篇文章。
Attribute 类型
该类型在讨论 Element 类型的 attributes 属性已有提及。元素的特性在 DOM 中以 Attr 类型表示。尽管他们是节点,但特性去不被认为是 DOM 文档树的一部分。一般通过 Elment 类型的方法增删改查元素的特性。
特征
- nodeType:Node.ATTRIBUTE_NODE(2)
- nodeName:特性的名称
- nodeValue: 特性的值。
- parentNode:
null
- (在 HTML 中) 没有子节点
对象的属性
- name:特性的名称,与 nodeName 的值一致。
- value:特性的值,与 nodeValue 的值一致。
- specified:是否自定义特性,布尔值。
DocumentFragment 类型
文档片段,在添加大量 DOM 节点时可作为"仓库",再一次性添加到文档中,以减少文档的回流和重绘。
特征
- nodeType:Node.DOCUMENT_FRAGMENT_NODE(11)
- nodeName: "#document-fragment"
- nodeValue:
null
- parentNode:
null
- 子节点的种类与 Element 类型一致
创建节点的方法
使用document.createDocumentFragment()
可以创建 DocumentFragment 节点,无传入参数。之后想 Element 类型一样使用appendChild()
方法为其添加子节点,删除和插入同理。
Text 类型
文本节点由 Text 类型表示,包含的是可以照字面解释的纯文本内容。纯文本中可以包含转移后的 HTML 字符,但不能包含 HTML 代码。
特征
- nodeType:Node.TEXT_NODE(3)
- nodeName: "#text"
- nodeValue:节点所包含的文本
- parentNode: Element 类型
- 没有子节点
对象的属性和方法
- data:该节点的文本内容,可读写,与"nodeValue"的值一致。
- appendData(text):添加文本到尾部。
- deleteData(offset, count):删除从 offset 位置开始的 count 个字符。
- insertData(offset, text):指定位置插入文本。
- replaceData(offset, count, text):替换指定位置的字符串。
- splitText(offset):从 offset 位置将文本节点分成两个。
- substringData(offset, count):提取指定位置的字符串。
创建节点的方法
使用document.createTextNode(text)
方法创建文本节点,"text" 只支持字符串,若文本内容包含 HTML 标签,只会被当成纯字符串解析。
Comment 类型
该类型表示的是注释节点。与 Text 类型继承自相同的基类,所以拥有splitText()
之外的所有字符串操作方法。
特征
- nodeType:Node.COMMENT_NODE(8)
- nodeName: "#comment"
- nodeValue:注释的内容
- parentNode: Document 类型 或 Element 类型
- 没有子节点
创建节点的方法
使用document.createComment(text)
可以创建注释节点,实际生产中很少会用到就不细说。
CDATASection 类型
该类型只针对基于 XML 的文档,表示的是 CDATA 区域。与 Comment 类型类似,继承自 Text 类型,所以拥有splitText()
之外的所有字符串操作方法。
特征
- nodeType:Node.CDATA_SECTION_NODE(4)
- nodeName: "#cdata-section"
- nodeValue:CDATA 区域中的内容
- parentNode: Document 类型 或 Element 类型
- 没有子节点
创建节点的方法
使用document.createCDataSection(text)
可以创建 CDATASection 节点,传入节点的内容即可。
DocumentType 类型
包含着与文档的 doctype 有关的所有信息。对象保存在document.doctype
中。
特征
- nodeType:Node.DOCUMENT_TYPE_NODE(10)
- nodeName: doctype 的名称
- nodeValue:
null
- parentNode: Document 类型
- 没有子节点
对象的属性
- name:文档类型的名称,如
<!DOCTYPE HTML>
中 name 的值为"HTML"。
关于性能的两点
- 尽量减少 NodeList 的访问次数,因为每次对其访问,都会运行一次基于文档的查询。
- 添加对 DOM 大量元素时(如列表项),应使用 DocumentFragment 作为仓库存放,在一次性添加到指定位置。