前端开发中经常遇到需要动态给某个元素外面套一层容器的情况。比如原本一个孤零零的按钮,产品突然要求给它加个带边框和阴影的包裹层;或者一组列表项需要用 div 包起来做滚动区域。这时候如果去改 HTML 模板当然可以,但如果是在 JS 里动态处理,jQuery 的 wrap() 方法就是专门解决这类问题的。
wrap() 的作用是给每个被选中的元素外面包裹一层指定的 HTML 元素。它不会改变原有元素在 DOM 中的位置,只是在外面加了一层父容器。这个方法接受字符串、jQuery 对象或者 DOM 元素作为包裹内容,灵活度很高。
语法形式
$(selector).wrap(wrappingElement, function(index))
wrappingElement(必填):指定用什么元素来包裹。可以传 HTML 字符串如 "<div class='wrapper'></div>",也可以传已有的 jQuery 对象或 DOM 元素。
function(index)(可选):一个回调函数,index 是当前元素在中的索引。函数返回的 HTML 字符串或元素会作为该元素的包裹容器。当中不同位置的元素需要不同的包裹结构时,这个参数就很关键。
基础示例:给段落包裹 div
下面这个例子用按钮触发,给页面上的每个 p 元素外面都套上一个带粉色背景的 div。动手试一下就能直观理解 wrap() 的效果。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>wrap 基础示例</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<style>
.pkg {
background-color: #f5b7b1;
padding: 8px;
margin-bottom: 6px;
}
</style>
</head>
<body>
<p>欢迎学习 jQuery 编程</p>
<p>这是一段示例文字</p>
<button id="wrapBtn">给每个段落包裹 div</button>
<script>
$(document).ready(function(){
$("#wrapBtn").click(function(){
$("p").wrap("<div class='pkg'></div>");
});
});
</script>
</body>
</html>
点击按钮后,用浏览器开发者工具查看 DOM 结构,会发现每个 p 外面都多了一个 div.pkg。原来的 HTML 从:
<p>欢迎学习 jQuery 编程</p>
<p>这是一段示例文字</p>
变成了:
<div class="pkg"><p>欢迎学习 jQuery 编程</p></div>
<div class="pkg"><p>这是一段示例文字</p></div>
进阶示例:点击触发包裹操作
第二个示例演示了一个更实际的场景:页面上有几个方块和一个目标文本,点击方块后把目标文本用动态创建的 div 包裹起来。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>wrap 进阶示例</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<style>
.block {
margin: 5px;
padding: 2px;
border: 2px solid #555;
width: 60px;
display: inline-block;
text-align: center;
cursor: pointer;
}
.wrap-box {
margin: 10px 0;
padding: 6px;
border: 2px solid #c0392b;
background-color: #f9ebea;
display: inline-block;
}
</style>
</head>
<body>
<p>点击任意方块来包裹下方文字:</p>
<div class="block" style="background-color:#e67e22;">ONE</div>
<div class="block" style="background-color:#f1c40f;">TWO</div>
<div class="block" style="background-color:#2ecc71;">THREE</div>
<br><br>
<span id="targetText">这段文字将会被包裹</span>
<script>
$(document).ready(function(){
$("div.block").click(function(){
var wrapper = '<div class="wrap-box"></div>';
$("#targetText").wrap(wrapper);
});
});
</script>
</body>
</html>
点击任意方块,#targetText 就会被套上一个带红色边框的 div.wrap-box。连续点击多次会持续嵌套,每点一次就多一层包裹。如果实际项目中不想重复包裹,可以在 wrap() 前加判断,比如检查目标元素的父元素是否已经有特定类名。
wrap() 的几个使用细节
包裹的内容会复制还是移动? 如果传给 wrap() 的是页面上已经存在的元素,jQuery 会复制这个元素作为包裹容器,而不是把原有元素移动过去。但一般更常见的做法是直接传 HTML 字符串,这样每次都是新建一个元素。
和 wrapAll() 的区别要分清。 wrap() 是给每个匹配元素各包一层,wrapAll() 是把所有匹配元素包在同一个容器里。比如页面有三个 p,$("p").wrap("<div>") 会产生三个 div 各包一个 p;$("p").wrapAll("<div>") 则是一个 div 包住全部三个 p。项目开发里这两个方法用错的情况不少,关键是想清楚你需要的是每个元素独立包裹还是统一包裹。
回调函数在批量操作中的作用。 假设一个表格里每行的单元格需要根据列索引包上不同样式的容器,这时候用回调函数就很顺手:
$("td").wrap(function(index){
if(index % 2 === 0){
return "<div class='even-col'></div>";
} else {
return "<span class='odd-col'></span>";
}
});
这种写法比先选中再分开两次 wrap() 简洁不少。
什么时候用 wrap()
个人经验里,wrap() 在以下几种场景中出现频率比较高:
-
动态创建弹窗或提示框时,给触发元素包裹一层定位参照容器
-
表格需要横向滚动时,用 JS 给
table外包一层div设置overflow-x:auto -
表单校验时,给校验不通过的输入框外包一层带红色边框的容器来提示错误
-
图片懒加载时,给
img外包一层占位容器保持布局稳定
凡是需要在不改动原始 HTML 的情况下给元素加父容器的需求,wrap() 基本都能胜任。比手动用 before() 插入开始标签再用 after() 插入结束标签的方式要方便得多,也不容易出错。
本节课程知识要点
-
wrap()给每个选中元素各包裹一层指定的 HTML 元素,不改变原有元素的 DOM 位置。 -
包裹参数可以是 HTML 字符串、jQuery 对象或 DOM 元素,HTML 字符串是最常用的形式。
-
回调函数参数
index让批量操作中可以根据元素位置提供不同的包裹内容,灵活度更高。 -
与
wrapAll()的区别:wrap()是每个元素各包一层,wrapAll()是所有元素包在一起。 -
多次调用
wrap()会持续嵌套,需要防重复包裹时应在调用前加判断逻辑。
wrap() 解决的是一个很具体的需求——在已有元素外面加容器。它的设计把“插入父级包裹元素”这个操作封装成了一个方法调用,省去了手动拼接 HTML 标签的麻烦。配合 unwrap()(移除父级包裹)和 wrapAll()(统一包裹),jQuery 在 DOM 结构动态调整方面的能力基本覆盖了大部分日常开发场景。理解清楚这几个方法各自的行为边界,写 DOM 操作代码时会更加得心应手。