image-20260212203819527

DOM核心知识

注意: 本章知识仅适用于Web前端开发学习路线或全栈开发路线,如果仅使用JavaScript做后端开发,不强制要求学习。

前面我们为大家介绍了JS的基础语法部分,这一章我们将继续深入Web浏览器环境,学习然后控制页面上的元素并实现各种高级操作。

元素和属性

在实际开发中,我们经常需要动态控制页面上的元素样式,比如当鼠标点击元素时,我们可以改变它的颜色,点击按钮时可以展示弹窗,用户滑动窗口时实时展示当前滚动的进度。这些效果都需要通过DOM提供的方法来实现,我们可以利用JavaScript与其进行交互,让我们的网站动起来。

DOM介绍

DOM(Document Object Model,文档对象模型)可以理解为:浏览器把 HTML 页面转换成的一棵“对象树”。这棵树里的每一个节点,都是 JavaScript 可以操作的对象。比如下面的代码:

html Copy
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Title</title>
  </head>
  <body>
    <div>我是页面上的一段普通内容</div>
    <p>我是一个段落</p>
  </body>
</html>

浏览器会把上面的代码自动转换为下面的树形结构:

image-20260212212153383

在HTML中,这种结构叫做DOM树,我们需要将这个树形结构倒过来看,HTML元素就是这棵树的树根,而它的子元素,实际上就是这棵树上的分支。所有的元素,在浏览器加载页面后,会在内存中生成一个对应的 DOM 节点对象,此时 JavaScript 就可以直接操作这个节点。

在JS中,节点分为很多种类型,一共有14种类型,但其中比较常见的是以下五种类型:

  1. 元素节点ELEMENT_NODE):操作 HTML 元素的核心。
  2. 文本节点TEXT_NODE):处理元素内的文本内容。
  3. 注释节点COMMENT_NODE):有时用于模板标记或调试。
  4. 文档节点DOCUMENT_NODE):全局 document 对象,用于访问整个页面。
  5. 文档片段节点DOCUMENT_FRAGMENT_NODE):高效批量添加 DOM 元素。

比如我们编写的元素就是一个节点,也就是 HTML 标签本身,它是页面结构的核心组成部分,下面这些都是元素节点:

html Copy
<div class="container"></div>
<p>Hello World</p>
<a href="https://example.com">链接</a>

而文本节点,就是包含在元素或属性中的纯文本内容,包括空格、换行等空白字符:

html Copy
<div>
  这里是文本节点
  <p>Hello <span>World</span></p>
</div>

此外,HTML 中的注释内容,虽然不会在页面中显示,但可以通过 DOM 访问,这些是注释节点:

html Copy
<!-- 这是一个注释节点 -->

整个文档的根就是文档节点,一般情况下是html标签:

html Copy
<html lang="en">
  ...
</html>

几乎在HTML文件中出现的所有内容,都会变成一个JS可以控制的节点,哪怕是注释也会被算在其中。因此,DOM 让 JavaScript 有了“操作页面的能力”。下一节我们将介绍如何通过JS获取DOM上的节点。

获取元素

在操作页面之前,第一步永远是:先找到元素,通过JS查找元素有很多种方式,浏览器为我们提供了多种“查找 DOM 元素”的方式,下面我们从最基础、最容易理解的方法开始,一步步往后讲。

我们需要用到doucment对象,它是整个DOM的总管,代表当前这个HTML文档,我们可以通过它来获取DOM上的任何内容。第一种是通过 id 获取元素(getElementById)这是最常用、也是新手最先学会的方法

js Copy
document.getElementById(id)

这里的参数是 元素的 id 名称(字符串),返回值是 一个元素对象,如果找不到元素,则返回 null

html Copy
<div id="box">我是一个盒子</div>
js Copy
const box = document.getElementById('box')
console.log(box)

可以看到,这里得到了一个HTML元素对象,类型是HTMLElement,HTML中所有的元素类型都是Node的子类,继承关系和顺序如下:

  1. EventTarget:最顶层的基类,让对象拥有处理事件的能力(比如 addEventListener)。
  2. Node:基础的节点类,DOM 树中的所有内容(标签、文本、注释等)都是 Node。
  3. Element:更具体的节点,它专门指代“标签”,提供了处理属性(Attribute)的方法。
  4. HTMLElement:HTML 专用的元素,它包含了所有 HTML 标签共有的属性(比如 id, className, style)。
  5. 具体标签(如 HTMLDivElement):特定标签的属性(比如 <a> 标签独有的 href

我们如果直接打印它,会以HTML代码的形式在控制台展示:

image-20260213012627718

我们可以通过nodeType来获取它的具体类型:

js Copy
console.log(box.nodeType === Node.ELEMENT_NODE)

由于得到的结果是一个数字,我们直接使用Node构造函数中提供的常量来进行比较即可。

当然,我们也可以在一个单独的JS文件中编写这段代码:

html Copy
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script src="js/script.js"></script>
</head>
js Copy
//script.js
const box = document.getElementById('box')
console.log(box)

此时我们会发现,这样好像不太行,控制台中获取到的元素是一个null

image-20260213115140379

这其实是因为我们的JS引入是写在head标签内的,而页面内容是在body中,网页的加载顺序是从上往下进行的,当JS加载的时候,页面内容还未渲染完成(DOM树还未完成构建)所以就无法拿到需要的元素了。

这里推荐几种做法,最简单的就是将 <script> 标签移到 </body> 结束标签之前:

html Copy
<body>
  <div>我是页面上的一段普通内容</div>
  <div id="box">我是一个盒子</div>
  <!-- 放在最后执行,此时前面的元素都已经完成加载 -->
  <script src="js/script.js"></script>
</body>

还有一种方法是给 <script> 添加 defer 属性,这个属性可以使得JS延迟加载,确保脚本执行时能访问到所有 DOM 元素:

html Copy
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script defer src="js/script.js"></script>
</head>

我们也可以使用getElementsByTagName根据标签名字一次性获取所有元素:

js Copy
document.getElementsByTagName("div")
image-20260213123903844

这里得到的是一个HTMLCollection,它是一个类数组(array-like)集合对象,包含了一组有序的 DOM 元素,使用方法非常简单:

js Copy
const elements = document.getElementsByTagName("div")
console.log(elements.item(0))   //使用item访问指定下标的元素
console.log(elements[1])   //也可以和数组一样玩
image-20260213141603054

此外,HTMLCollection还提供了一个namedItem用于快速查找集合中nameid属性为指定值的元素:

js Copy
console.log(elements.namedItem("box"))

我们也可以使用getElementsByClassName通过 class 名称来获取元素:

js Copy
const elements = document.getElementsByClassName("item")
console.log(elements)
html Copy
<div class="item">A</div>
<div class="item">B</div>

我们还可以根据name属性来获取元素,这个方法在现代开发中用得不多,主要用于表单:

html Copy
<input type="text" name="username">
<input type="password" name="password">
js Copy
const inputs = document.getElementsByName('username')

除了根据名字属性获取外,document上直接提供了根元素的获取,documentElement直接代表页面根元素,也就是html元素:

js Copy
document.documentElement
image-20260213153648979

此外,body属性也是直接代表body这个元素:

image-20260213160213836

最后我们来介绍一个最重要的,也是开发中最常用的一种元素获取方式,querySelector可以使用 CSS 选择器获取单个元素:

js Copy
document.querySelector("#box")

要判断我们的选择器是否使用正确,也可以使用matches进行判断:

js Copy
box.matches("#box")   //当CSS选择器匹配时,返回真

利用这个方法,可以替代前面讲到的全部方法,只要CSS选择器编写合理,就能直接选择需要的元素,非常方便。不过需要注意的是,这个方法只会返回匹配到的第一个元素,如果需要一次性获取所有满足CSS选择器的元素,可以使用querySelectorAll方法:

js Copy
document.querySelectorAll(".item")

它会返回一个NodeList对象,和我们前面介绍的HTMLCollection不同的是,HTMLCollection 仅包含 **Element(元素节点)**比如 <div><p> 等标签。而 NodeList 包含所有 Node(节点)元素,所以还包括文本节点(换行、空格)、注释节点以及属性节点,因为CSS选择器选择的范围更加广泛,所以它应该包含更多种类。它提供了forEach用于快速遍历子节点:

js Copy
document.querySelectorAll(".item").forEach((value, key, parent) => {
    console.log(key, value, parent)   //key就是顺序下标,value就是节点本身,parent就是当前这个节点列表
})

此外,还有一个非常重要的是,HTMLCollection是动态的,一旦DOM发生变化,这个对象会跟着变化,而NodeList是获取时产生的静态快照,我们可以尝试在打印对象之后删除页面上的一个元素:

image-20260213152017011

此时HTMLCollection的长度会变化成1,而NodeList无感。

以上讲解的方法,除了在document上使用,我们也可以在任意一个元素上使用,来实现快速查找子元素:

js Copy
const box = document.getElementById('box')
box.querySelector("p")   //直接在这个box元素上查找内部符合条件的子元素

此外,我们还可以使用:

js Copy
element.closest('.container')   //用于向上查找符合选择器的祖先元素

查找到元素之后,我们就可以开始愉快的操控它了。

HTML属性

在前面我们已经学会了如何获取元素,但仅仅拿到元素还不够,真正让页面“动起来”的关键,是读取和修改元素的属性属性(Attribute),简单理解就是写在 HTML 标签上的那些“信息”,比如:

html Copy
<div id="box" class="item" title="提示文本"></div>

这里的 idclasstitle,都是元素的属性,这是我们在HTML中为大家介绍的。需要获取HTML标签上的属性,我们可以直接使用getAttribute方法:

js Copy
console.log(element.getAttribute("id"))

注意返回值永远是字符串,因为属性都是直接写的值,如果属性不存在,会返回 null。除了获取之外,我们也可以使用setAttribute来修改某个属性:

js Copy
element.setAttribute("class", "666")
image-20260214170321600

如果这个属性不存在,那么将会新增这个属性:

js Copy
box.setAttribute("data-v-25565", "666")
image-20260214171513288

不过,对于一些非标准的HTML标签属性,我们更建议大家使用后续DOM属性中的dataset来实现。

对于一些布尔属性来说,设置不需要填写特别的内容,如果要使用直接设置值为空即可,如果不需要则移除属性,比如:

html Copy
<input disabled="disabled">
js Copy
input.removeAttribute('disabled') // 表示 false
input.setAttribute('disabled', '') // 表示 true

这里需要注意的是,HTML 属性名本身不区分大小写,所以即使我们写一个大写的也会变成小写形式,覆盖也会按照小写的形式去进行覆盖:

js Copy
box.setAttribute("CLASS", "666")
image-20260214171915265

不过,这里还是建议大家在 JavaScript 中调用方法时,属性名统一推荐使用小写,这是业界的通用约定,避免出现兼容性和可读性问题。

有时候我们并不关心属性的值,只关心它有没有被写在标签上,这时可以使用hasAttribute来判断:

js Copy
element.hasAttribute('title')

我们也可以使用 removeAttribute 删除某个属性:

js Copy
element.removeAttribute('title')

如果属性本身不存在,不会报错,但也不会有任何效果。

DOM属性

在上一节中我们讲了 HTML 属性(Attribute),它们是写在标签上的信息。而这一节要讲的 DOM 属性(Property),是浏览器在内存中为每一个元素创建的 JavaScript 对象属性。所以,HTML 属性是“写给浏览器看的”,DOM 属性是“写给 JavaScript 用的”。

当浏览器加载 HTML 页面时,会做两件事:

  1. 解析 HTML 标签上的属性(Attribute)
  2. 基于这些属性,生成一个对应的 DOM 对象

比如一个input标签:

html Copy
<input type="text" value="hello">

浏览器会创建一个 HTMLInputElement 对象,其中包含大量 DOM 属性:

js Copy
input.value
input.type
input.disabled
input.checked
input.placeholder

这些属性并不一定全部写在 HTML 中,但 只要元素类型支持,就一定存在于 DOM 对象上。想要直接观察DOM元素的各个属性,可以直接打开开发者工具,然后再元素界面选择需要观察的元素,接着在下面找到属性:

image-20260124000847227

DOM 属性的访问方式非常直观,就像普通 JS 对象一样,比如我们想要修改元素的id属性,直接对其进行修改即可,修改后会立即生效到元素上:

js Copy
const box = document.getElementById('box')
box.id = 'crazy'
image-20260214210437028

对于一些非标准HTML属性,我们也可以使用dataset来实现:

js Copy
box.dataset.role = 'guest'
image-20260215153512552

此外,它还可以实现自动解析驼峰的效果:

js Copy
console.log(box.dataset.userId)  //获取的其实是data-user-id

不过,和前面介绍的 HTML 属性的一个区别是,DOM 属性的值不一定是字符串。比如一些布尔属性,它们的值就是布尔类型的:

js Copy
console.log(box.draggable)  //false

这里我们着重介绍两个比较常用的DOM属性,首先是用于设置classclassNameclassList属性:

js Copy
console.log(box.className)   //字符串结果
box.className = "crazy item"

修改className后,元素的class属性也会一起跟着变化,但是如果我们需要追加新的类,还需要手动进行拼接,这显然是非常麻烦的,所以我们更推荐大家使用下面的classList属性来修改类,它使用起来更加方便:

js Copy
console.log(box.classList)   //得到一个类列表

这里得到的是一个DOMTokenList对象,它可以实现对所有以空格分割的属性进行快捷编辑,我们可以直接通过它来进行类的增加和删除,直接使用add就可以插入新的类了,就像使用数组那样:

js Copy
box.classList.add('crazy', 'thursday', 'vivo', '50yuan')
image-20260214215036006

我们也可以使用remove来对属性进行删除:

js Copy
box.classList.remove("item")
image-20260214215306162

其他方法也很好用:

js Copy
box.classList.toggle('active')   //切换类,如果有则删除,没有就新增
box.classList.toggle('active', true)   //切换类,强制设置
box.classList.contains('active')   //判断是否包含类
box.classList.replace("item", "crazy")  //把一个类替换成另外一个类

我们接着来看如何更改内联样式,使用style即可:

html Copy
<div id="box" style="background: pink">我是文本</div>
js Copy
console.log(box.style)

style属性中包含了目前几乎所有可用的CSS属性,需要调整哪个属性,只需要直接对其进行赋值即可。比如我们现在需要修改文本的颜色:

js Copy
box.style.color = 'white'   //等价于 color: white; 白色
image-20260214225933760

此时页面上的元素style属性也会跟着发生变化,每个属性的设置都是独立的,不会影响其他属性。

当然,DOM属性不仅包含HTML标签上的属性,还有一些元素自己本身的属性,比如前面介绍的innerTextnodeType等,其实都是DOM属性。有关其他DOM属性,我们会在后续课程中逐步进行讲解,大家在使用时也可以在MDN文档上自行查询需要的属性。

元素内容

在前面我们已经学习了如何获取元素,以及元素的属性,这一节我们接着来介绍几个比较特殊的属性,它们可以操控元素的内容。在所有的元素对象中,innerHTML 用来 获取或设置元素内部的 HTML 结构

html Copy
<div id="box">
  <span>hello</span>
</div>
js Copy
const box = document.getElementById('box')
console.log(box.innerHTML)
// <span>hello</span>

可以看到,innerHTML代表的是元素内部的HTML文档结构,打印出来的值也是一个HTML格式的代码。同样的,既然可以获取,我们也可以使用这个属性来修改内部的HTML代码:

js Copy
box.innerHTML = '<p>新的内容</p>'
image-20260213164153780

虽然这种做法在修改HTML结构上简单粗暴,但是它存在诸多问题,其中最主要的就是安全和性能问题:

  1. 当你修改 innerHTML 时,浏览器并不会只更新你改动的那一小部分,浏览器必须销毁该元素下所有的旧 DOM 节点,重新解析 HTML 字符串,并创建新的 DOM 对象,大规模的 DOM 变更会触发昂贵的浏览器重排(Reflow)和重绘(Repaint),在循环中使用 innerHTML += '...' 更是性能自杀。
  2. 如果你直接把用户输入的数据赋给 innerHTML,就相当于给黑客开了后门,因为客户可以利用这种方式在你的网页上直接插入javascript标签来执行恶意JS代码。
  3. innerHTML 对格式要求极严。如果你不小心传入了未闭合的标签(比如 <div>文字),浏览器会尝试自动修复,但这往往会导致最终生成的 DOM 结构和你预期的完全不同,甚至引发布局崩坏。
  4. 如果你用 innerHTML 覆盖了一个容器,即便你只是改了一行文字,原本绑定在容器内部子元素上的所有 Event Listeners(事件监听器)都会随之消失(后续章节会介绍事件监听机制)

因此,如果实在需要增加删除或是修改元素,我们更推荐使用后续章节中讲到的方法来操作,而不是直接修改HTML内容。如果仅仅只是修改页面上的文字内容,建议使用下面的textContent方式。

除了innerHTML之外,还有innerText,它可以用来获取或设置 “人眼能看到的文本”

html Copy
<div id="box">Hello World</div>

或是这种嵌套写法,都只会解析可视文本部分:

html Copy
<div id="box">
  Hello <span>World</span>
</div>
js Copy
console.log(box.innerText)   //Hello World

注意,如果文本内容是不可见的,那么这里得到的结果也会是一个空字符串:

html Copy
<div id="box" style="visibility: hidden">Hello World</div>

最后,还有一个textContent,它的功能和innerText差不多,也可以用来获取或设置 纯文本内容,但是它不会受到可视性影响:

js Copy
console.log(box.textContent)   //即使不可见依然可以得到正确结果

此外,针对于HTML中的换行也会一起保留下来,而innerText是渲染之后的实际展示文本,不会保留换行:

html Copy
  <div id="box" style="visibility: hidden">Hello
    World</div>
image-20260213172145204

相比innerText,它获取内容的性能更高,因为前者需要计算布局(Reflow)来确定文本是否可见。但是,一些特殊标签里面的内容也会被textContent拿到:

html Copy
<div id="box">
  <script>
      for (let i = 0; i < 6; i++) {
          console.log("孩子们,这并不好笑")
      }
  </script>
</div>
image-20260213172358089

innerText则会绕过这些实际不可见的内容。无论使用textContent还是innerText,我们都可以对内容进行修改,但是注意,这里设置的是纯文本内容,也就是普通文本元素:

js Copy
box.textContent = "卡布奇诺今犹在,不见当年倒茶人"
js Copy
box.innerText = "卡布奇诺今犹在,不见当年倒茶人"
image-20260213172609962

注意,由于这里仅仅只是文本内容设置,所以即使我们设置一段HTML代码,也会被自动转义为文本形式的内容,变成普通文本元素:

js Copy
box.innerText = "<div>卡布奇诺今犹在,不见当年倒茶人</div>"
image-20260213173110970

由于textContent不考虑实际渲染样式,所以在外面修改内容时浏览器不需要重新计算布局,在性能上相比innerText更加稳定,如果要频繁对页面内容进行修改,建议优先考虑textContent

除了使用inner获取内容外,我们还可以使用outer来获取包含元素本身在内的全部内容:

js Copy
console.log(box.outerHTML)
image-20260215143630779

注意,当我们替换outerHTML内容时,会连带整个标签一起变化。

还有outerText,但是这个属性默认情况下和innerText其实是一致的,不过,如果我们尝试修改它,它会连带着整个标签一起变成普通文本:

js Copy
box.outerText = "牛逼啊"
image-20260215145045049

创建和操作元素

前面我们介绍了如何修改内容,只需要利用innerHTML / innerText / textContent属性即可。但是实际上,直接对innerHTML进行修改会导致一些性能问题,这一节我们就介绍一下更多关于 DOM 的增删改操作

想在页面中新增一个元素,第一步一定是创建它document对象为我们提供了一个createElement方法可以快速创建一个新的元素:

js Copy
const div = document.createElement('div')
div.textContent = '我是新创建的元素'   //和普通元素一样,可以正常设置属性

不过,这仅仅只是在内存中创建了一个新的元素,此时在页面上还看不到任何变化。创建完元素之后,一定要插入到 DOM 树中,我们可以使用appendChild方法来将它添加到某个元素的内部,作为子元素存在:

js Copy
const box = document.getElementById('box')
const div = document.createElement('div')
div.textContent = '我是新创建的元素'
//调用父元素的appendChild方法为其添加这个新创建的元素到内部
box.appendChild(div)
image-20260213192117331

注意,appendChild只会在原有基础上新增子元素,如果原本就存在子元素,则会自动添加到原本存在元素的后面:

image-20260213192700748

还有一个比较有意思的是,如果这个元素不是我们创建的,而是原本在页面上就存在的,那么将其添加到新的位置后,相当于是从原来的位置移动到这个新的位置上,而不是复制一个新的元素插入:

js Copy
const box = document.getElementById('box')
const item = document.querySelector('.item')
//实际上是将这个元素移动到box的下面
box.appendChild(item)

除了原本的appendChild,我们也可以使用append方法来实现元素插入,效果是完全一样的,但是它支持填入多个元素,按照顺序一次性插入:

js Copy
const box = document.getElementById('box')
const div = document.createElement('div')
div.textContent = '我是新创建的元素'
const item = document.querySelector('.item')
box.append(div, item)

此外,除了插入元素之外,append还可以直接插入一个字符串,这个字符串直接作为文本元素存入。

js Copy
const box = document.getElementById('box')
box.append("我是文本内容")
image-20260213193511262

这里除了创建简单元素之外,实际上document还为我们提供了很多不同的节点类型创建:

js Copy
document.createTextNode('hello')   //可以实现创建一个文本节点
document.createComment("这是注释")   //创建注释

这里需要注意的是,虽然append可以实现节点插入,但是依然会出现前面提到的性能问题,如果我们需要一次性插入多个节点,建议使用DocumentFragment,它就像是一个临时的小DOM树,也可以增删DOM元素,我们可以先把要插入的元素放入其中,之后一次性进行插入:

js Copy
const fragment = document.createDocumentFragment();  //创建一个临时dom树
//添加元素到fragment中
box.append(fragment)

这也可以极大地优化批量插入元素的情况,相比for循环每次插入都会导致元素重新计算发生重排,这种方式会大大减少重排次数,提高性能。

当然,既然可以在尾部插入元素,我们也可以在首部插入元素,新元素会出现在 第一个子节点的位置

js Copy
const box = document.getElementById('box')
box.prepend(div, item, "我是文本内容")   //效果和上面一样,但是在元素内部的前面插入

我们还可以实现精确位置插入,使用insertBefore可以实现在指定元素的前面插入,比如我们现在想要插入到这个p子标签的前面:

html Copy
<div id="box">
  <a>你干嘛</a>
  <p>哎哟</p>
</div>
js Copy
const box = document.getElementById('box')

const div = document.createElement('div')
div.textContent = '我是新创建的元素'
//除了直接使用document来查询元素之外,我们还可以对着任意一个元素进行查询
const p = box.querySelector('p')

box.insertBefore(div, p)  //这里的意思将div插入到p之前

不过,这种方式只能往某个元素的前面插入,用起来不是很方便。这里更建议大家使用更加万能的元素插入操作insertAdjacentElement,它的参数可以自由控制插入点,相比前面几种更加方便:

js Copy
const box = document.getElementById('box')
const div = document.createElement('div')
div.textContent = '我是新创建的元素'
const p = box.querySelector('p')
//第一个参数用于控制插入点,beforebegin 就是在它本身之前
box.insertAdjacentElement('beforebegin', div)
image-20260214000419704
position 位置说明 示意
"beforebegin" 在 target 前面(当兄弟) target 之前
"afterbegin" 在 target 内部最前 第一个子元素
"beforeend" 在 target 内部最后 最后一个子元素
"afterend" 在 target 后面(当兄弟) target 之后

如果只是单纯插入一个文本元素,那么直接使用insertAdjacentText,它可以实现普通文本插入:

js Copy
box.insertAdjacentText('beforebegin', "我是文本内容")

当然,如果你希望插入一段HTML代码,也可以使用insertAdjacentText

js Copy
box.insertAdjacentText('beforebegin', "我是文本内容")

除此之外,还有insertAdjacentHTML方法可以实现对HTML代码的插入,但是注意,这种方式和innerHTML一样,存在一些性能问题和XSS攻击问题。

介绍完元素的插入,我们接着来看元素的删除,删除非常简单,只需要直接对着元素自己调用remove方法即可:

js Copy
const box = document.getElementById('box')
box.remove()   //移除自己

当然,我们也可以通过removeChild来移除子元素,但是这里需要传入子元素(那我干嘛不直接对着子元素remove呢)

js Copy
const box = document.getElementById('box')
const p = box.querySelector('p')
box.removeChild(p)

然后是元素的替换操作,使用replaceChild即可替换某个指定元素:

js Copy
const box = document.getElementById('box')
const p = box.querySelector('p')
const a = document.createElement('a')
a.textContent = '点我啊哥哥'
//第一个参数是新的元素,第二个参数是原本需要被替换的
box.replaceChild(a, p)

我们还可以使用replaceChildren来实现对所有子元素的替换:

js Copy
box.replaceChildren(a, "我是普通文本元素")

replaceChildren会移除所有子元素,并将给到的元素替换进去。

除了对子元素进行替换之外我们也可以直接对某个元素进行替换,使用replaceWith替换:

js Copy
const box = document.getElementById('box')
const a = document.createElement('a')
a.textContent = '点我啊哥哥'
//直接替换调用元素
box.replaceWith(a)
//也可以一次性传入多个元素,包括文本元素也是可以的,注意不会进行HTML转换
box.replaceWith(a, "我是普通文本元素")
正在載入頁面,請稍後...