前面分别讲了 wrap() 和 wrapInner(),现在来看包裹系列方法里的第三个——wrapAll()。这个方法的行为和前两个有明显区别:它把所有选中的元素统一包进一个容器里,而不是像 wrap() 那样给每个元素各包一层。
这个区别在效果上非常大。假设页面有三个 p 标签:
<p>段落一</p>
<p>段落二</p>
<p>段落三</p>
用 $("p").wrap("<div>") 的结果是每个 p 外面各有一个 div:
<div><p>段落一</p></div>
<div><p>段落二</p></div>
<div><p>段落三</p></div>
而用 $("p").wrapAll("<div>") 的结果是一个 div 包住了全部三个 p:
<div>
<p>段落一</p>
<p>段落二</p>
<p>段落三</p>
</div>
这个差异决定了 wrapAll() 的典型使用场景——当需要把一组零散的同级元素归拢到一个父容器里时,它就是优选方案。
语法形式
$(selector).wrapAll(wrappingElement)
wrapAll() 只有一个必填参数,没有 wrap() 和 wrapInner() 里那个可选的 function 回调。参数类型同样是 HTML 字符串、jQuery 对象或 DOM 元素。
基础示例:统一包裹段落
下面这个简单示例用按钮触发,把两个 p 元素统一包进一个粉色背景的 div 中。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>wrapAll 基础示例</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<style>
.container {
background-color: #f5b7b1;
padding: 12px;
margin-top: 6px;
}
</style>
</head>
<body>
<p>欢迎学习 jQuery 编程</p>
<p>前端开发从入门到实践</p>
<button id="wrapAllBtn">用 div 包裹所有段落</button>
<script>
$(document).ready(function(){
$("#wrapAllBtn").click(function(){
$("p").wrapAll("<div class='container'></div>");
});
});
</script>
</body>
</html>
点击按钮后,两个 p 被移进新创建的 div.container 里,整个区域出现粉色背景。用开发者工具查看 DOM 能清楚地看到结构变化。
进阶示例:包裹方块到新容器
下面这个例子更有意思。页面上有几个分散的方块,点击任意一个,就把所有方块统一包进一个新的 div 里。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>wrapAll 进阶示例</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<style>
.box {
margin: 8px;
padding: 8px;
border: 2px solid #555;
width: 80px;
display: inline-block;
text-align: center;
cursor: pointer;
font-weight: bold;
}
.wrapper {
margin: 10px;
padding: 12px;
border: 3px solid #c0392b;
background-color: #fdedec;
}
</style>
</head>
<body>
<p>点击任意方块,把所有方块包进新容器:</p>
<div class="box" id="targetBox">目标文本</div>
<div class="box" style="background-color:#e67e22;">方块A</div>
<div class="box" style="background-color:#f1c40f;">方块B</div>
<div class="box" style="background-color:#2ecc71;">方块C</div>
<script>
$(document).ready(function(){
$("div.box").click(function(){
var wrapper = "<div class='wrapper'></div>";
$("div.box").wrapAll(wrapper);
});
});
</script>
</body>
</html>
点击任意方块后,四个方块全部被归拢到一个红色边框的 div.wrapper 中。注意看 $("div.box") 这个选择器——它会匹配页面上所有带 box 类的 div,所以一次 wrapAll() 就把它们全包起来了。
wrapAll 和 unwrap 配合使用
wrapAll() 有个天然的搭档叫 unwrap(),作用是移除选中元素的父容器。两者配对使用,可以实现“添加外层包裹”和“撤销外层包裹”的完整操作闭环。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>wrapAll 与 unwrap 配合示例</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<style>
.pkg {
background-color: #d6eaf8;
padding: 10px;
border: 2px solid #2471a3;
margin-top: 8px;
}
</style>
</head>
<body>
<p>学习 jQuery 包裹方法</p>
<p>wrapAll 与 unwrap 配合</p>
<button id="btnWrap">包裹段落</button>
<button id="btnUnwrap">解除包裹</button>
<script>
$(document).ready(function(){
$("#btnWrap").click(function(){
$("p").wrapAll("<div class='pkg'></div>");
});
$("#btnUnwrap").click(function(){
$("p").unwrap();
});
});
</script>
</body>
</html>
先点“包裹段落”,两个 p 被包进蓝色边框的容器;再点“解除包裹”,容器被移除,两个 p 恢复原样。反复点击可以反复切换。这个交互模式在折叠面板、选项卡组件、动态分组等功能里很常见。
wrapAll 使用中需要注意的细节
wrapAll() 会改变元素在 DOM 中的位置。如果选中的元素原本分散在不同父容器里,执行 wrapAll() 后它们会被提取出来放到新容器中。这可能会导致原有布局发生变化,因为元素离开了原本的 DOM 位置。
举个例子,如果页面结构是这样的:
<div class="section-a"><p>段落一</p></div>
<div class="section-b"><p>段落二</p></div>
执行 $("p").wrapAll("<div class='new-wrapper'>") 后,两个 p 都会从原来的父容器中移出,一起放进新创建的 div.new-wrapper。原来的 section-a 和 section-b 会变成空容器。这种“移动”行为有时候是故意为之(归拢元素),有时候是副作用。使用前确认清楚选中元素的原始位置关系很重要。
wrap、wrapInner、wrapAll 三者区别
到现在讲了包裹系列的全部三个方法,放一起梳理一下:
| 方法 | 操作对象 | 包裹位置 | 典型场景 |
|---|---|---|---|
wrap() |
每个选中元素 | 元素外部各包一层 | 给列表项加边框容器 |
wrapInner() |
每个选中元素 | 元素内容外面 | 高亮文本、加内联样式标签 |
wrapAll() |
所有选中元素 | 统一包进一个容器 | 把分散元素归拢成一组 |
本节课程知识要点
-
wrapAll()把所有选中元素统一包裹进一个容器,而不是每个元素各包一层。 -
该方移动选中元素在 DOM 中的位置,将它们放入新创建的包裹容器中。
-
配合
unwrap()可以实现包裹与解包裹的完整交互逻辑。 -
wrapAll()只有wrappingElement一个参数,不支持 function 回调。 -
使用前注意选中元素原本的 DOM 位置,避免意外的布局变化。
wrapAll() 解决的需求很明确——把一组同级元素归拢到一个容器里统一管理。和 wrap() 的“各包各的”以及 wrapInner() 的“包内容”不同,wrapAll() 做的是“合并收纳”。三个包裹方法各有分工,覆盖了 DOM 结构调整中关于元素包裹的三种方向。把它们放在一起对比掌握,写 JS 操作页面结构的时候思路会更清晰,该用哪个方法一看需求就能判断出来。