在动态页面中,有时你需要将一个 DOM 元素整体替换成另一个元素或一段 HTML 结构。jQuery 的 replaceWith() 方是为此设计的——它把选中的每个元素从 DOM 中移除,并在原位置插入你指定的新内容。
replaceWith() 有一个功能上等价但写法相反的方法 replaceAll()。两者的目标相同,只是调用者和参数的位置对调:$("p").replaceWith("<div/>") 是从旧元素出发去替换,而 $("<div/>").replaceAll("p") 是从新内容出发去替换旧元素。选择哪种写法主要取决于你手头已有的对象是什么——如果你手里拿着新内容的 HTML 字符串,用 replaceAll() 会更自然;如果你已经通过选择器拿到了要被替换的元素,用 replaceWith() 的链式调用会更顺畅。
为什么我倾向于用 replaceWith() 而不是先插入再删除?
手动先 before() 或 after() 插入新内容,再 remove() 删除旧元素,需要两步操作且容易出现中间状态闪烁。replaceWith() 将这两个动作合为一个原子操作,性能更高,也不会出现元素短暂共存或短暂缺失的过渡状态。
语法
$(selector).replaceWith(newContent, function(index))
参数说明:
-
newContent(必需):用来替换选元素的內容。可以是 HTML 字符串、DOM 元素对象、或 jQuery 对象。 -
function(index)(可选):一个回调函数,返回用于替换的内容。函数接收index参数表示当前元素在中的索引位置(从 0 开始)。每个被选中的元素都会调用一次这个函数,你可以根据索引为不同的元素生成不同的替换内容。
课程知识要点
-
彻底替换:
replaceWith()会把旧元素连同它绑定的事件和数据从 DOM 中彻底移除,新内容不会继承旧元素的事件处理器。 -
函数参数实现差异化替换:通过回调函数可以根据每个元素的索引动态生成不同的替换内容,不必写多段重复代码。
-
与 replaceAll() 方向相反:
A.replaceWith(B)等价于B.replaceAll(A),两者互为镜像。 -
事件处理器丢失:替换后旧元素上绑定的事件会一并销毁。如果新内容需要绑定事件,需在替换操作后重新绑定。
-
索引从 0 开始:回调函数中的
index遵循 jQuery 惯例,第一个匹配元素的索引是 0。
示例一:用固定内容替换多种元素
这个例子展示了使用 newContent 参数,将不同类型的元素替换为新的 HTML 结构。一个 div 变成 h1 标题,另一个 div 变成 h2 标题,按钮自身也被替换掉。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>replaceWith() 基础替换 · 编程学习</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<style>
div {
border: 2px dashed #1a73e8;
margin: 8px 0;
padding: 8px;
font-size: 20px;
text-align: center;
}
.new-box {
border: 2px solid #d93025;
width: 180px;
height: 40px;
background-color: #fff3cd;
}
</style>
<script>
$(document).ready(function () {
$("button").click(function () {
// 将第一个 div 替换为 h1
$("#card1").replaceWith("<h1>编程学习社区欢迎你</h1>");
// 将第二个 div 替换为 h2
$("#card2").replaceWith("<h2>jQuery 入门教程</h2>");
// 将提示段落替换为新文本
$("#tip").replaceWith("<p>替换操作已完成。</p>");
// 将按钮自身替换为一个新 div
$("#btn").replaceWith("<div class='new-box'></div>");
});
});
</script>
</head>
<body>
<p>这是一个演示 jQuery replaceWith() 方法的示例。</p>
<div id="card1">这是第一个 div 元素</div>
<div id="card2">这是第二个 div 元素</div>
<p id="tip">点击下方按钮执行替换操作:</p>
<button id="btn">点击替换</button>
</body>
</html>
点击按钮后,两个 div 变成了不同级别的标题,提示段落内容更新,按钮自身被一个实线边框的盒子取代。每个替换都是独立完成的,互不影响。
示例二:使用回调函数按索引生成差异化内容
当你需要为中的每个元素生成不同的替换内容时,回调函数提供了索引参数来区分每个元素的位置。下面的例子中,页面上有三个带 mark 类的段落和两个 div,点击按钮后它们分别被替换为带有索引编号的新标题。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>replaceWith() 函数参数替换 · 编程学习</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<style>
div {
border: 2px dashed #1a73e8;
margin: 8px 0;
padding: 8px;
text-align: center;
}
h3 {
background-color: #fff3cd;
color: #1a73e8;
}
h4 {
background-color: #e8f0fe;
color: #d93025;
}
</style>
<script>
$(document).ready(function () {
$("button").click(function () {
// 将所有带 mark 类的段落替换为 h4,内容包含索引
$(".mark").replaceWith(function (index) {
return "<h4>被替换的段落,原索引: " + index + "</h4>";
});
// 将所有 div 替换为 h3,内容包含索引
$("div").replaceWith(function (index) {
return "<h3>被替换的 div,原索引: " + index + "</h3>";
});
});
});
</script>
</head>
<body>
<p>这是一个演示 replaceWith() 函数参数的示例。</p>
<div>这是第一个 div 元素</div>
<p class="mark">这是第一个带标记的段落</p>
<div>这是第二个 div 元素</div>
<p class="mark">这是第二个带标记的段落</p>
<p class="mark">点击下方按钮执行替换:</p>
<button id="btn">点击替换</button>
</body>
</html>
点击按钮后,三个 mark 类段落分别被替换为 h4,内容中显示各自的原始索引(0、1、2);两个 div 分别被替换为 h3,同样带有各自的索引编号。通过回调函数,一段代码就完成了对整个的差异化替换。
在开发中,replaceWith() 有几个值得留意的使用场景和注意事项。
动态模板渲染:当后端返回的 JSON 数据需要渲染成卡片列表时,可以先给每个占位容器标记统一的类名,遍历数据后在循环中逐个 replaceWith() 为真实的 HTML 结构。如果需要配合事件绑定,记得在替换完成后用事件委托或在替换内容插入后再绑定。
表单控件切换:在单选/多选场景中,有时需要根据用户选择将下拉框替换为输入框,或反过来。replaceWith() 可以在不改变父容器结构的情况下完成控件类型切换,代码简洁。
事件丢失问题:这是使用 replaceWith() 时容易被忽略的一点。旧元素上的事件处理器、.data() 绑定的数据都会随元素被移除而销毁。如果你的新内容同样需要事件绑定,替换后需重新绑定。或者考虑使用事件委托,将事件绑定在不会被替换的父容器上,这样无论内部子元素如何替换,事件都能正常触发。
避免在循环中频繁调用:如果需要替换大量元素,尽量先构建完整的 HTML 字符串,再用一次 replaceWith() 或 replaceAll() 来操作,而不是在循环中对每个元素单独调用。每次调用都会触发 DOM 重排,累积起来性能损耗会很明显。