news 2026/10/6 2:28:00

Modern JavaScript Tutorial 实战:用 insertAdjacentHTML 在列表中精准插入 HTML 节点

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Modern JavaScript Tutorial 实战:用 insertAdjacentHTML 在列表中精准插入 HTML 节点
  • 文档/教程
  • 前端

【免费下载链接】en.javascript.info

Modern JavaScript Tutorial

项目地址:https://gitcode.com/gh_mirrors/en/en.javascript.info
点击查看免费下载

导读

本篇基于 Modern JavaScript Tutorial(现代 JavaScript 教程)仓库中 "Insert the HTML in the list" 练习任务,讲解如何在两个既有<li>之间插入一段 HTML,并借此深入掌握 DOM 修改的核心工具之一——insertAdjacentHTML。你将学会四个插入位置参数的区别、它与append/before/after等现代插入方法的取舍,以及"按 HTML 插入"与"按文本插入"在安全性上的本质差异,能够直接应用于动态列表、菜单、消息提示等页面渲染场景。

任务还原:在列表中间插入 HTML

原任务(task.md)给出的 HTML 结构如下:

<ul id="ul"> <li id="one">1</li> <li id="two">4</li> </ul>

任务要求编写代码,把<li>2</li><li>3</li>插入到两个<li>之间,即最终得到:

<ul id="ul"> <li id="one">1</li> <li id="two">2</li> <li id="three">3</li> <li id="two">4</li> </ul>

这个任务本身考察的是:当需要把一段结构化的 HTML 字符串(包含标签)插入到文档中某个相对位置时,应该选择哪个 DOM 方法。任务的答案与完整讲解位于同目录的 solution.md 与所属章节 article.md。

参考答案:insertAdjacentHTML('afterend', ...)

任务的官方参考解法只有一行:

one.insertAdjacentHTML('afterend', '<li>2</li><li>3</li>');

这行代码的含义是:以id="one"的<li>元素为基准,把 HTML 字符串插入到它之后(即<li id="two">4</li>之前)。由于<li>1</li>与<li>4</li>是相邻的兄弟节点,插入到第一个元素后面,恰好就落在两者之间。

为什么任务推荐insertAdjacentHTML而不是innerHTML拼接?核心原因是:insertAdjacentHTML只影响目标位置附近的节点,而innerHTML会整体重写整个父元素的内容。如果对ul.innerHTML做字符串拼接,需要先读出原有 HTML、手动拼接、再写回,既繁琐又容易破坏原本绑定在节点上的引用与事件。insertAdjacentHTML则把"在哪里插入"和"插入什么"两个问题清晰拆开。

深入理解:四个插入位置参数

elem.insertAdjacentHTML(where, html)的第一个参数where必须是四个关键字之一(详见 article.md 的 "insertAdjacentHTML/Text/Element" 一节):

位置关键字插入效果
"beforebegin"插入到elem之前(与elem成为兄弟节点)
"afterbegin"插入到elem内部、最前面(成为第一个子节点)
"beforeend"插入到elem内部、最后面(成为最后一个子节点)
"afterend"插入到elem之后(与elem成为兄弟节点)

仓库中的 insert-adjacent.svg 用图示直观展示了这四种插入点:

其中afterbegin/beforeend等价于"在目标元素内部的首/尾"插入,而beforebegin/afterend则是"在目标元素外部的前/后"插入。回到任务场景:one.insertAdjacentHTML('afterend', ...)使用的是兄弟级插入点,因此不会触碰ul内部的其他子节点,也不会触发任何重新解析整个列表的开销。

结合示例理解四个位置的差异(示例同样来自 article.md):

<div id="div"></div> <script> div.insertAdjacentHTML('beforebegin', '<p>Hello</p>'); div.insertAdjacentHTML('afterend', '<p>Bye</p>'); </script>

最终 DOM 为:

<p>Hello</p> <div id="div"></div> <p>Bye</p>

为什么不用after()直接插入节点?

也许你会想到更现代的写法one.after(...)。它确实能实现同样的效果,但有一个关键区别:before/after/append/prepend会把字符串参数按"纯文本"插入,而不是按 HTML 解析。

以任务为例,如果用one.after('<li>2</li><li>3</li>'),浏览器不会创建两个<li>元素,而是插入一个包含尖括号字面量的文本节点——页面上会直接显示&lt;li&gt;2&lt;/li&gt;&lt;li&gt;3&lt;/li&gt;这串字符,这正是 article.md 强调的:"strings are inserted in a safe way, likeelem.textContentdoes it"。

因此:

  • 要插入DOM 节点或纯文本(希望自动转义),用append/prepend/before/after;
  • 要插入一段可解析的 HTML 字符串(带标签、样式、结构),用insertAdjacentHTML。

仓库中的对比图 before-prepend-append-after.svg 展示了现代插入方法的效果:

另外请注意:现代插入方法的参数可以是"任意多个节点或字符串"的列表,且字符串会自动转为文本节点。而insertAdjacentHTML的第二个参数始终是单个 HTML 字符串。

文本安全性与textContent的配合

insertAdjacentHTML的"按 HTML 解析"特性既是能力也是风险。当用户输入可能包含<b>、<script>等标签时,直接插入 HTML 会导致内容被当作标记执行或渲染。

仓库中两个相邻任务正好互为印证:

  1. createTextNode vs innerHTML vs textContent 任务 指出:elem.append(document.createTextNode(text))与elem.textContent = text效果完全一致,都会把字符串作为纯文本放入元素;而elem.innerHTML = text会作为 HTML解析。二者结果截然不同,这正是"按文本插入"与"按 HTML 插入"的分水岭。
  2. Create a list 任务 要求"如果用户输入 HTML 标签,应将其按文本对待",其 参考实现 正是通过li.textContent = data配合ul.append(li)完成动态列表构建——即先创建<li>元素,再用textContent安全赋值。

所以正确的选择标准是:

  • 内容来源可信、可控(如模板字符串、服务端渲染好的片段)→ 可用insertAdjacentHTML;
  • 内容来自用户输入或不可信来源→ 使用textContent/createTextNode,或用createElement创建元素后逐个属性赋值,避免 XSS。

两个"兄弟"方法:insertAdjacentText与insertAdjacentElement

insertAdjacentHTML还有两个语法完全一致的兄弟方法(见 article.md):

  • elem.insertAdjacentText(where, text)—— 同样的四个位置关键字,但第二个参数按纯文本插入;
  • elem.insertAdjacentElement(where, elem)—— 同样的四个位置关键字,但第二个参数是一个DOM 元素。

它们存在的意义主要是让插入 API 的语法保持"统一"。在实践中,大多数情况下只用insertAdjacentHTML,因为插入元素和文本时,append/prepend/before/after写起来更短、且天然支持多参数批量插入。例如 article.md 中的消息提示示例,就用insertAdjacentHTML("afterbegin", ...)把带样式的提示块插到页面顶部。

实战扩展:同类动态列表场景的三种写法

把任务的思想推广到"动态生成列表"场景,仓库给出了多种等价实现路径,可根据需求选择:

写法一:insertAdjacentHTML(字符串模板,适合内容可信时)

let ul = document.getElementById('ul'); for (let i = 2; i <= 3; i++) { ul.insertAdjacentHTML('beforeend', `<li>${i}</li>`); }

写法二:createElement + append(节点方式,适合需要引用或事件绑定)

let li = document.createElement('li'); li.textContent = i; // 文本安全 ul.append(li); // 追加到列表末尾

写法三:DocumentFragment 批量插入(减少重排,适合大批量)

article.md 的 DocumentFragment 一节演示了把多个<li>先装进 fragment、再一次插入:

let fragment = new DocumentFragment(); for (let i = 1; i <= 3; i++) { let li = document.createElement('li'); li.append(i); fragment.append(li); } ul.append(fragment); // fragment 会"融入",其子节点直接成为 ul 的子节点

更简化的等价写法是返回节点数组后用展开运算符一次插入:

ul.append(...getListContent());

小结

  • 在两个既有兄弟节点之间插入一段 HTML 字符串时,one.insertAdjacentHTML('afterend', '<li>2</li><li>3</li>')是官方推荐方案:精准、不重写父元素、字符串按 HTML 解析;
  • insertAdjacentHTML的四个位置关键字beforebegin/afterbegin/beforeend/afterend覆盖了"元素外前后"与"元素内首尾"全部插入点;
  • append/prepend/before/after适合插入节点或需要转义的纯文本,insertAdjacentHTML适合插入结构化 HTML,二者互补而非替代;
  • 涉及用户输入时,优先textContent或createElement构造节点,避免直接插入 HTML 带来的 XSS 风险;
  • 大批量插入节点时可借助DocumentFragment或数组展开一次性完成。

如需继续深入,可在仓库中对照阅读 章节全文 article.md、任务解答 solution.md,以及安全文本处理的 Create a list 任务,形成完整的"创建 → 插入 → 移除 → 克隆"DOM 操作知识链。

  • 文档/教程
  • 前端

【免费下载链接】en.javascript.info

Modern JavaScript Tutorial

项目地址:https://gitcode.com/gh_mirrors/en/en.javascript.info
点击查看免费下载

相关推荐

上一篇:终极阴阳师自动化脚本:从零开始解放双手的完整指南
下一篇:游戏资源逆向工程实战:UABEA在Unity资源编辑与模组制作中的专业应用

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/6 2:27:36

VAR-MATH: Probing True Mathematical Reasoning in Large Language Models via Symbolic Multi-Instanc...

文章主要内容和创新点 主要内容 文章聚焦于大型语言模型(LLMs)在数学推理能力评估中的局限性,指出现有模型在标准数学基准测试上的性能提升可能源于对特定模式的过拟合,而非真正的推理能力。具体而言: 现有评估存在两大缺陷:一是基准污染(公开测试题可能导致数据泄露,…

作者头像 李华
网站建设 2026/10/6 2:24:16

GetQzonehistory:把QQ空间历史说说一键备份成本地Excel和HTML

GetQzonehistory&#xff1a;把QQ空间历史说说一键备份成本地Excel和HTML 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 翻空间找三年前发过的某条动态&#xff0c;翻到手指酸也定位不…

作者头像 李华