在调整页面布局时,一个很常见的需求是:某个容器里已经有一堆子元素,现在需要把这批子元素统一装进一个新创建的 div 里,形成一层新的嵌套结构。比如给旧页面内容统一加一个带样式的容器、为列表内容添加滚动包裹层,或者做动画时需要一个统一的定位父级。手动修改 HTML 显然不够灵活,尤其是内容是动态生成的情况下。jQuery 提供的 wrapInner 方法正是为这类场景设计的,下面详细介绍它的用法和相关的几个容易混淆的方法。

一、使用 wrapInner 把子元素整体包进新 div
wrapInner 的作用是:在匹配元素的内部,把所有子内容(包括文本节点和子元素)包裹到指定结构里。也就是说,新创建的 div 会成为原容器的唯一子元素,而原来的所有子元素都会被移动到这个新 div 内部。
先准备一段基础的结构:
<div id="box">
<p>第一段内容</p>
<p>第二段内容</p>
</div>用一行 jQuery 代码就能完成包裹:
$('#box').wrapInner('<div class="inner"></div>');执行后 DOM 结构变为:
<div id="box">
<div class="inner">
<p>第一段内容</p>
<p>第二段内容</p>
</div>
</div>可以看到,两个 p 元素连同它们之间的空白文本节点都被完整地搬进了 inner 这个 div 中。原容器的 id、class 等属性不受任何影响,只是内部多了一层。这一点很重要:如果你在 box 上绑定了事件,事件依然有效,因为 box 本身没有被替换。
wrapInner 的参数除了 HTML 字符串,还可以是元素对象或 jQuery 对象。例如你可以先用 $('
// 先创建并配置包裹层
var wrapper = $('<div>', {
'class': 'inner-wrapper',
css: { padding: '10px', background: '#f5f5f5' }
});
// 再执行包裹
$('#box').wrapInner(wrapper);这种写法的好处是包裹层的样式、属性、甚至预先绑定的事件都可以在创建阶段完成,逻辑上比拼接 HTML 字符串更安全,也避免了字符串中引号转义的麻烦。
二、wrap、wrapAll 与 wrapInner 的区别
这三个方法名字相近,行为却完全不同,是实际使用中最容易混淆的地方。简单概括:wrap 是给每个匹配元素各自包一层,wrapAll 是把所有匹配元素作为一个整体包进同一层,wrapInner 则是包裹元素内部的内容。
假设有如下结构:
<div class="container">
<p class="item">A</p>
<p class="item">B</p>
<p class="item">C</p>
</div>三种方法的效果对比如下:
// 1. wrap:每个 p 各自被一个 div 包住
$('.item').wrap('<div class="w"></div>');
// 结果:div.w > p(A),div.w > p(B),div.w > p(C)
// 2. wrapAll:三个 p 一起被同一个 div 包住
$('.item').wrapAll('<div class="w"></div>');
// 结果:div.w > p(A) + p(B) + p(C)
// 3. wrapInner:每个 p 内部的文本被包住
$('.item').wrapInner('<div class="w"></div>');
// 结果:p > div.w > 文本回到标题的需求——把某个容器的子元素包进新 div,正确的选择是 wrapInner 作用于容器本身。不少初学者会误写成 $('#box').wrap(...),结果是容器自身被包了一层,内容结构没有变化,这是最典型的误区。判断方法很简单:想包裹“自己”用 wrap,想包裹“孩子”用 wrapInner。
另外要注意 wrapAll 的一个特性:如果匹配的元素在 DOM 中不是连续排列的,wrapAll 会把后面的元素移动到第一个元素的位置,统一放进包裹层。这种隐式的 DOM 移动可能影响布局顺序,使用时需要留意。
三、动态内容的包裹与常见实战场景
实际项目中,子元素经常是异步加载或动态生成的。这时不能只在页面初始化时执行一次包裹,否则后插入的内容不会被包进去。常见做法是在内容插入完成后再执行 wrapInner:
$.ajax({
url: '/api/list',
method: 'GET',
success: function (data) {
var html = data.map(function (item) {
return '<p>' + item.text + '</p>';
}).join('');
$('#box').html(html)
.wrapInner('<div class="list-inner"></div>');
}
});如果需要多次操作,还要防止重复包裹。可以先判断内层 div 是否已存在:
function ensureWrapper() {
var $box = $('#box');
// 如果还没有内层容器,才执行包裹
if (!$box.find('> .inner').length) {
$box.wrapInner('<div class="inner"></div>');
}
}这里用 find('> .inner') 只查找直接子级,避免误判深层嵌套里同名的元素。
另一个典型场景是给旧页面内容统一添加滚动容器。旧页面容器可能同时设置了 padding 和固定高度,直接在其内部加 overflow 滚动往往效果不理想,此时插入一层内 div 来承担滚动职责会很干净:
$('#legacy-box').wrapInner(
$('<div>', { css: { height: '100%', overflowY: 'auto' } })
);最后补充一个细节:unwrap 方法与 wrapInner 正好相反,用于移除包裹层但保留内容。如果包裹操作需要支持撤销,配合一个标记类名使用 unwrap 即可还原结构,这在需要切换布局状态的交互中非常实用。
总结一下,把子元素包进新建的内层 div,核心方法就是 wrapInner;需要逐个包裹子元素时改用 wrap 并选中子元素集合;需要整体包裹多个兄弟节点时用 wrapAll。理解三者作用于 DOM 的方向差异,就能在各类结构改造场景中游刃有余。
jQuery wrap子元素包裹div嵌套修改时间:2026-09-05 00:20:40