Skip to main content

DOM的增删改查

DOM 查询​

通过节点之间的关系查找​

image-20220130164437382

important

下面要介绍的所有属性都只是只读的,直接修改它们不会有任何作用,它们的作用是获取真实 DOM 节点对象的引用,我们可以通过引用做任何事情。

顶层节点​

节点说明
document整个 DOM 树的根节点
document.doctype表示 <!DOCTYPE html>
document.documentElement表示 <html>
document.head表示 <head>
document.body表示 <body>

父节点​

节点关系说明
node.parentNode返回 node 的父节点
node.parentElement返回 node 的父元素节点

为什么要区分 node.parentNode 和 node.parentElement,难道一个节点的父节点还可能不是 Element 类型的节点?

记住两个例外:document.doctype 和 document.documentElement 这两个节点的父节点是 document,它不是 Element 类型的节点。

兄弟节点​

节点关系说明
node.nextSibling返回 node 下一个兄弟节点
node.nextElementSibling返回 node 下一个兄弟元素节点
node.previousSibling返回 node 上一个兄弟节点
node.previousElementSibling返回 node 上一个兄弟元素节点

关于 nextSibling 和 nextElementSibling 的区别就是,前者是返回当前节点对象的下一个兄弟节点对象,这个节点对象可以是任何类型,后者则只获取它下一个元素类型的兄弟节点,如果是文本节点就会忽略掉。

比如对于一个 document.head 节点。

document.head.nextSibling; // #text,因为它们之间有一个换行和几个空格
document.head.nextElementSibling; // <body>

子节点​

节点关系说明
node.firstChild返回 node 的第一个子节点
node.firstElementChild返回 node 的第一个子元素节点
node.lastChild返回 node 的最后一个子节点
node.lastElementChild返回 node 的最后一个子元素节点
node.childNodes返回 node 的子节点类数组
node.children返回 node 的子元素节点类数组

node.childNodes 和 node.children 的区别是,前者可以返回该节点的所有类型的子节点,后者只能返回元素类型的子节点。并且它们返回的都是 类数组,没有原生数组上的方法。

对于判断一个元素是否有子节点,我们可以使用 elem.hasChildNodes() 方法。

node.childNodes 与 node.children 注意事项
  • 可以使用 for ... of 来遍历它们,不能使用数组中的方法
  • 我们不能通过修改 node.childNodes / node.children 来修改 node 的子节点结构,但是集合中保存了所有子节点对象的引用,我们可以利用子节点对象的引用做任何想做的事情

getElementBy*​

方法说明
document.getElementById(id)通过元素 id 获取到该元素
document.getElementsByName(name)通过元素上的 name 属性获取一个元素集合
`elem.getElementsByTagName(tag*)`
elem.getElementsByClassName(class)通过元素的类名获取一个元素集合
  • 任何具有 id 属性的标签,其 DOM 对象会以该 id 为 key,该 DOM 对象为 value 绑定在 widnow 对象上
  • 上面表格中的 API 只有后面两个可以在任意 DOM 对象上使用,前两个只能在 document 上使用
  • 上述 API 获取到的都是真实 DOM 对象的引用,意味着只要某个 DOM 对象发生变化或者被新增、删除,所获取到的元素集合也会实时变化

querySelector*​

方法说明
elem.querySelector(selector)通过 CSS 选择器查找到选择器的第一个元素
elem.querySelectorAll(selector)通过 CSS 选择器查找到选择器所有元素集合

两者的区别就是,前者返回的是第一个元素,后者返回的所有匹配上该选择器的元素集合。

对于上面两个 API,我们可以传入任何 CSS 选择器,甚至是伪类。比如 document.querySelector("input:hover") 将会返回鼠标当前正覆盖的的 input。

matches 与 closest​

elem.matches(selector) 的作用是检查该 elem 是否与给定的 CSS 选择器匹配。

elem.closest(selector) 的作用是获取 elem 最近的且匹配上 CSS 选择器的父元素。

创建 DOM 节点​

方法说明
document.createElement(tag: string)根据传入的标签字符串(小写)创建一个对应的 DOM 元素
document.createTextNode(value: string)根据传入的 value 创建一个文本节点
elem.cloneNode(deep: boolean)返回一个和当前节点结构完全相同,但是引用不同的 DOM 对象

这里注意一下 elem.cloneNode(),它的参数是一个布尔类型,默认情况下只会拷贝当前节点本身,不会填充其内部的子节点,如果填入 true,那么会将当前节点包含其子节点完整的结构拷贝下来。

并且返回的拷贝节点还有其所有的子节点,都是全新的引用。

插入 DOM 节点​

方法说明
node.append(...nodes or strings)在当前节点的 末尾 插入一系列节点或字符串
node.prepend(...nodes or strings)在当前节点的 开头 插入一系列节点或字符串
node.before(...nodes or strings)在当前节点的 前面 插入一系列节点或字符串
node.after(...nodes or strings)在当前节点的 后面 插入一系列节点或字符串

这里注意一下上面方法的参数可以为多个。

在 DOM 树中,同一个节点对象只能存在于一处位置,如果添加的新节点对象已经存在于 DOM 树中,那么会先将其在原 DOM 树删除,然后添加该节点在指定位置。

<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</body>

<script>
const ul = document.querySelector("ul");
const li = document.createElement("li");

ul.append(li);
ul.append(li);
ul.prepend(li);
</script>

在上面这个例子中,我们持续的向 ul 内添加同一个 li:

  • 执行第一次 append 时,会将 li 添加到 ul 的最后一个子元素
  • 执行第二次 append 时,由于该 DOM 节点已经存在 DOM 树中,则会删除 DOM 树中该节点,然后再添加 li
  • 最后执行 prepend 时,会删除 ul 中最后一个子节点,然后将 li 添加到 ul 的第一个子元素位置

另外,我们还可以使用下面这种更方便的方法,使用 where 参数来指定新元素的插入位置。

方法说明
elem.insertAdjacentHTML(where, html)将 html 文本插入到 elem 的指定位置
elem.insertAdjacentText(where, text)将字符串内容插入到 elem 的指定位置
elem.insertAdjacentElement(where, elem)将元素节点插入到 elem 指定位置

where 的取值必须为以下之一:

  • "beforebegin" — 相当于 node.before
  • "afterbegin" — 相当于 node.prepend
  • "beforeend" — 相当于 node.append
  • "afterend" — 相当于 node.after

pic.sm

替换 DOM 节点​

方法说明
elem.replaceWith(...nodes or strings)将当前元素用一系列节点或字符串替换
elem.replaceChildren(...nodes or strings)将当前元素的后代用一系列节点或者字符串替换
node.replaceChild(newChild, oldChild)将当前节点指定的旧节点对象删除,然后替换为新节点对象

移除 DOM 节点​

方法说明
node.remove()将当前元素从 DOM 树中删除

需要注意的是,如果我们要将一个元素 移动 到另一个地方,则无需将其从原来的位置中删除。

所有插入方法都会自动从旧位置删除该节点。

DocumentFragment​

这是一个特殊的 DOM 节点,可以把它当作一个替身,我们可以对其添加、删除、修改任何节点,最终将该节点添加到 DOM 树中就会显示我们对该节点操作后对结果。具体可以查看 DocumentFragment。

老式的方法​

做了解即可。

  • parent.appendChild(node)
  • parent.insertBefore(node, nextSibling)
  • parent.removeChild(node)
  • parent.replaceChild(newElem, node)
  • document.write