unwrap() 是包裹系列方法的反向操作。它做的事情很简单——把选中元素的直接父元素移除掉,但保留选中元素本身。如果说 wrap() 是给元素加个“外壳”,那 unwrap() 就是把这个“外壳”剥掉。
这个方法的典型用途是撤销之前用 wrap() 或 wrapAll() 添加的包裹容器。在需要动态切换页面结构的交互中,包裹和去包裹常常成对出现。
语法形式
$(selector).unwrap()
unwrap() 不需要任何参数。它直接作用于选中元素的父级,把父元素从 DOM 中移除。注意这里有个重要的行为细节:unwrap() 移除的是父元素,选中的元素本身完好保留,只是它在 DOM 树中的层级提升了一级。
基础示例:移除不同标签的父容器
下面这个例子展示了 unwrap() 的基本用法。页面上有两个 p 元素,一个被 div 包裹,一个被 article 包裹。点击按钮后,两个父容器都会被移除。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>unwrap 基础示例</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<style>
div {
background-color: #e67e22;
padding: 8px;
margin-bottom: 6px;
}
article {
background-color: #a9dfbf;
padding: 8px;
margin-bottom: 6px;
}
</style>
</head>
<body>
<div>
<p>这段文字在 div 里面</p>
</div>
<article>
<p>这段文字在 article 里面</p>
</article>
<button id="unwrapBtn">移除所有 p 元素的父容器</button>
<script>
$(document).ready(function(){
$("#unwrapBtn").click(function(){
$("p").unwrap();
});
});
</script>
</body>
</html>
点击按钮前,两个 p 分别有橙色和绿色背景的父容器。点击后,div 和 article 都被移除了,两个 p 直接出现在 body 下,背景色随之消失。这个例子直观地说明了一点:unwrap() 不关心父元素是什么标签,只要是直接父级,统统移除。
wrap 和 unwrap 配合使用
wrap() 和 unwrap() 是一对很自然的搭档。下面这个示例把两者整合在一起,提供包裹和解包裹两个按钮,可以反复切换。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>wrap 与 unwrap 配合示例</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<style>
.wrapper {
background-color: #d6eaf8;
padding: 10px;
border: 2px solid #2471a3;
margin-bottom: 6px;
}
</style>
</head>
<body>
<p>学习 jQuery 编程第一行</p>
<p>学习 jQuery 编程第二行</p>
<button id="btnWrap">给每个段落包裹 div</button>
<button id="btnUnwrap">解除包裹</button>
<script>
$(document).ready(function(){
$("#btnWrap").click(function(){
$("p").wrap("<div class='wrapper'></div>");
});
$("#btnUnwrap").click(function(){
$("p").unwrap();
});
});
</script>
</body>
</html>
交替点击两个按钮,可以在包裹和去包裹之间随意切换。这里有个细节值得留意:$("p").wrap() 是给每个 p 各包一个 div,所以执行一次会产生两个 div.wrapper。而 $("p").unwrap() 同样作用于全部 p,一次性把它们的父容器全部移除。两个方法的选择器一致,操作对称,写起代码来逻辑很清晰。
unwrap 使用时容易踩的坑
unwrap() 只移除直接父元素,不会跨层级操作。假如 DOM 结构有多层嵌套,比如:
<div class="outer">
<div class="inner">
<p>目标文字</p>
</div>
</div>
对 p 执行 unwrap(),只会移除最近的父级 div.inner,div.outer 会保留。如果想移除所有包裹层,需要多次调用或使用其他方法。
还有一个容易出错的地方:如果选中元素没有父级(比如本身就是 body 的直接子元素),unwrap() 不会报错但也不会执行任何操作。这个静默失败的机制在调试时需要注意,有时候满以为父元素会被移除却毫无反应,很可能就是选中的元素已经处于根层级了。
unwrap() 不能选择性移除父元素。如果页面上的 p 分别被 div、section、article 包裹,而你只想移除 div 类型的父容器,直接 $("p").unwrap() 会把所有父级都清掉。这种情况需要先筛选:
$("p").each(function(){
if($(this).parent().is("div")){
$(this).unwrap();
}
});
这种写法虽然多几行,但逻辑可控,不会误伤其他包裹容器。我个人在项目里更倾向这种显式判断的方式,而不是直接无脑 unwrap(),能减少很多意外。
和 remove() 的区别要分清
初学者有时会把 unwrap() 和 remove() 搞混,但两者操作的对象不同:
-
unwrap()移除的是选中元素的父元素,选中元素保留。 -
remove()移除的是选中元素本身,父元素不受影响。
简单记就是:unwrap() 剥壳不伤肉,remove() 连肉一起端。选对方法的前提是想清楚到底要删哪个层级的元素。
本节课程知识要点
-
unwrap()移除选中元素的直接父级,选中元素保留并提升到父级原本的位置。 -
不需要任何参数,调用方式简洁,但缺乏选择性,会无差别移除所有直接父元素。
-
配合
wrap()或wrapAll()使用,可以构建包裹与解包裹的完整交互闭环。 -
只作用于直接父级,多层嵌套时需多次调用或用
each()遍历处理。 -
与
remove()区别明显:unwrap()删父留子,remove()删子留父。
unwrap() 是 jQuery 包裹方法体系的收尾一环。到这里,wrap()、wrapInner()、wrapAll()、unwrap() 四个方法构成了一个完整的 DOM 包裹操作工具集。加外壳、包内容、统一收纳、剥外壳——四个方向覆盖了页面元素结构调整中最常见的包裹类需求。把这些方法的行为边界和互相之间的区别理解透,在写动态 DOM 操作的代码时思路会更清楚,也能少踩一些层级错乱的坑。