DOM
一、导航获取DOM节点
给定一个 DOM 节点,我们可以使用导航(navigation)属性访问其直接的邻居。
这些属性主要分为两组:
- 对于所有节点:
parentNode
,childNodes
,firstChild
,lastChild
,previousSibling
,nextSibling
。 - 仅对于元素节点:
parentElement
,children
,firstElementChild
,lastElementChild
,previousElementSibling
,nextElementSibling
。
二、直接搜索获取DOM节点
有 6 种主要的方法,可以在 DOM 中搜素节点:
Method | Searches by... | Can call on an element? | Live? |
querySelector |
CSS-selector | ✔ | - |
querySelectorAll |
CSS-selector | ✔ | - |
getElementById |
id |
- | - |
getElementsByName |
name |
- | ✔ |
getElementsByTagName |
tag or '*' |
✔ | ✔ |
getElementsByClassName |
class | ✔ | ✔ |
目前为止,最常用的是 querySelector
和 querySelectorAll
,但是 getElementBy*
可能会偶尔有用,或者可以在就脚本中找到。
此外:
elem.matches(css)
用于检查elem
与给定的 CSS 选择器是否匹配。elem.closest(css)
用于查找与给定 CSS 选择器相匹配的最近的祖先。elem
本身也会被检查。
让我们在这里提一下另一种用来检查子级与父级之间关系的方法,因为它有时很有用:
- 如果
elemB
在elemA
内(elemA
的后代)或者elemA==elemB
,elemA.contains(elemB)
将返回 true。
三、DOM节点属性
每个 DOM 节点都属于一个特定的类。这些类形成层次结构(hierarchy)。完整的属性和方法集是继承的结果。
主要的 DOM 节点属性有:
nodeType
- 我们可以使用它来查看节点是文本节点还是元素节点。它具有一个数值型值(numeric value):
1
表示元素,3
表示文本节点,其他一些则代表其他节点类型。只读。 nodeName/tagName
- 用于元素名,标签名(除了 XML 模式,都要大写)。对于非元素节点,
nodeName
描述了它是什么。只读。 innerHTML
- 元素的 HTML 内容。可以被修改。
outerHTML
- 元素的完整 HTML。对
elem.outerHTML
的写入操作不会触及elem
本身。而是在外部上下文中将其替换为新的 HTML。 nodeValue/data
- 非元素节点(文本、注释)的内容。两者几乎一样,我们通常使用
data
。可以被修改。 textContent
- 元素内的文本:HTML 减去所有
<tags>
。写入文本会将文本放入元素内,所有特殊字符和标签均被视为文本。可以安全地插入用户生成的文本,并防止不必要的 HTML 插入。 hidden
- 当被设置为
true
时,执行与 CSSdisplay:none
相同的事。
DOM 节点还具有其他属性,具体有哪些属性则取决于它们的类。例如,<input>
元素(HTMLInputElement
)支持 value
,type
,而 <a>
元素(HTMLAnchorElement
)则支持 href
等。大多数标准 HTML 特性(attribute)都具有相应的 DOM 属性。
四、特性和属性(操作特性的方法)
- 特性(attribute)— 写在 HTML 中的内容。
- 属性(property)— DOM 对象中的内容。
简略的对比:
属性 | 特性 | |
---|---|---|
类型 | 任何值,标准的属性具有规范中描述的类型 | 字符串 |
名字 | 名字(name)是大小写敏感的 | 名字(name)是大小写不敏感的 |
操作特性的方法:
elem.hasAttribute(name)
— 检查是否存在这个特性。elem.getAttribute(name)
— 获取这个特性值。elem.setAttribute(name, value)
— 设置这个特性值。elem.removeAttribute(name)
— 移除这个特性。elem.attributes
— 所有特性的集合。
在大多数情况下,最好使用 DOM 属性。仅当 DOM 属性无法满足开发需求,并且我们真的需要特性时,才使用特性,例如:
- 我们需要一个非标准的特性。但是如果它以
data-
开头,那么我们应该使用dataset
。 - 我们想要读取 HTML 中“所写的”值。对应的 DOM 属性可能不同,例如
href
属性一直是一个 完整的 URL,但是我们想要的是“原始的”值。
五、修改DOM的方法
-
创建新节点的方法:
document.createElement(tag)
— 用给定的标签创建一个元素节点,document.createTextNode(value)
— 创建一个文本节点(很少使用),elem.cloneNode(deep)
— 克隆元素,如果deep==true
则与其后代一起克隆。
-
插入和移除节点的方法:
node.append(...nodes or strings)
— 在node
末尾插入,node.prepend(...nodes or strings)
— 在node
开头插入,node.before(...nodes or strings)
— 在node
之前插入,node.after(...nodes or strings)
— 在node
之后插入,node.replaceWith(...nodes or strings)
— 替换node
。node.remove()
— 移除node
。
文本字符串被“作为文本”插入。
-
这里还有“旧式”的方法:
parent.appendChild(node)
parent.insertBefore(node, nextSibling)
parent.removeChild(node)
parent.replaceChild(newElem, node)
这些方法都返回
node
。 -
在
html
中给定一些 HTML,elem.insertAdjacentHTML(where, html)
会根据where
的值来插入它:"beforebegin"
— 将html
插入到elem
前面,"afterbegin"
— 将html
插入到elem
的开头,"beforeend"
— 将html
插入到elem
的末尾,"afterend"
— 将html
插入到elem
后面。
另外,还有类似的方法,elem.insertAdjacentText
和 elem.insertAdjacentElement
,它们会插入文本字符串和元素,但很少使用。
-
要在页面加载完成之前将 HTML 附加到页面:
document.write(html)