本节说一下DOM操作模块里的包裹元素子模块,该模块可将当前匹配的元素替换指定的DOM元素,有如下方法:

  • wrap(html)               ;在每个匹配元素的外层添加一层DOM元素                                ;该方法会遍历匹配元素集合,在每个元素上调用.wrapAll()方法        ;不同于wrapAll()的是该方法会在每个匹配元素外面都套一层html元素。
  • wrapAll(html)            ;会将html转化为一个DOM节点并放在第一个匹配元素的前面,再把其他匹配元素也依次放进去    ;html可以是html片段、选择器表达式、jQuery对象、DOM元素或函数,下同。
  • wrapInner(html)        ;在每个匹配元素的内容前后包裹HTML元素    ;该方法会遍历匹配元素集合,并通过调用方法.wrapAll()为每个匹配元素的所有内容包裹一段HTML结构。
  • unwrap()                  ;移除匹配元素集合中每个元素的父标签,并把匹配元素留在父元素的位置上

举个栗子:

writer by:大沙漠 QQ:22969969

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="http://libs.baidu.com/jquery/1.7.1/jquery.min.js"></script>
</head>
<body>
<p>你好</p>
<p>Hello World</p>
<div>
<i>
<span>测试文本</span>
</i>
</div> <button id="b1">按钮1</button> <br/>
<button id="b2">按钮2</button><button id="b3">按钮3</button> <br/>
<button id="b4">按钮4</button><br/><button id="b5">按钮5</button>
<script>
b1.onclick=function(){$('p').wrap('<div></div>')} //内部将<div></div>转化为jQuery对象放到第一个匹配元素<p>你好</p>之前,再将匹配元素移动到该DOM节点内部 b2.onclick=function(){$('p').wrapAll('<div></div>')} //内部将<div></div>转化为jQuery对象放到第一个匹配元素<p>你好</p>之前,再将匹配元素移动到该DOM节点内部
b3.onclick=function(){$('p').wrapAll('<div><p></p></div>')} //如果含有子节点,则会将匹配元素移动到子节点里面 b4.onclick=function(){$('p').wrapInner('<div></div>')} //在每个匹配元素的内容前后添加一层DOM节点(包裹层) b5.onclick=function(){$('span').unwrap() } //移除每个匹配元素的父元素,并让匹配元素占有该节点位置
</script>
</body>
</html>

渲染如下:

对应的DOM树如下:

点击按钮1会在所有的P标签上加一个div父节点,如下:

点击按钮2将在第一个p标签前添加一个div,然后把所有p标签放到div之下,如下:

点击按钮3将在第一个p标签前添加一个div>p双层DOM,然后把所有p标签放到div之下,如下:

点击按钮4将在p标签内最外层嵌套一层div标签,如下:

点击按钮5将会去除 span的上一层DOM节点,如下:

如果再次点击,会将span的上一层DOM继续移除,直到遇到body节点为止

源码分析


wrapInner和wrap都是基于wrapAll实现的,wrapAll实现如下:

jQuery.fn.extend({
wrapAll: function( html ) { //在匹配的元素外面放置html元素。html参数可以是html片段、选择器表达式、jQuery对象、DOM元素或函数。
if ( jQuery.isFunction( html ) ) { //如果html是函数
return this.each(function(i) {
jQuery(this).wrapAll( html.call(this, i) ); //遍历匹配元素,在每个匹配元素上执行html函数,并用该函数的返回值作为参数迭代调用.wrapAll()函数。
});
} if ( this[0] ) { //如果当前有匹配元素
// The elements to wrap the target around
var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); //将html转化为一个jQuery对象 if ( this[0].parentNode ) { //如果当前第一个匹配元素有父元素,
wrap.insertBefore( this[0] ); //则把创建的包裹元素插入第一个匹配元素之前。
} wrap.map(function() { //遍历wrap元素
var elem = this; //elem是创建的包裹元素的引用 while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { //如果html里含有一个子节点
elem = elem.firstChild; //则重置elem为html的子节点,上面的按钮3会执行到这里
} return elem;
}).append( this ); //这一行的this是当前匹配的jQuery对象,把每个匹配元素移动到插入的元素之后
} return this;
},
})

wrapAll首先会把参数转化为一个jQuery对象,然后插入到当前第一个匹配元素的前面,最后以生成的jQuery对象为主句,调用append()将当前匹配匹配的所有元素添加到新生成的jQuery对象对应的DOM节点内部。对应上面的按钮2

wrap()实现如下:

jQuery.fn.extend({
wrap: function( html ) { //在每个匹配元素的外层添加一层DOM元素
var isFunction = jQuery.isFunction( html ); //在每个匹配元素前后包裹一段HTML结构,该方法会遍历匹配元素集合,在每个元素上调用.wrapAll()方法。
return this.each(function(i) {
jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); //依次调用wrapALl()函数
});
},
})

wrapInner的实现如下:

jQuery.fn.extend({
wrapInner: function( html ) { //用于在匹配元素集合中每个元素的内容前后包裹一段HTML结构,该方法会遍历匹配元素集合
if ( jQuery.isFunction( html ) ) { //如果html是函数
return this.each(function(i) {
jQuery(this).wrapInner( html.call(this, i) ); //遍历匹配元素,在每个匹配元素上执行html函数,并用该函数的返回值作为参数迭代调用.wrapInner()函数。
});
} return this.each(function() { //遍历匹配元素集合
var self = jQuery( this ),
contents = self.contents(); //先获取所有子节点 if ( contents.length ) { //如果有子节点
contents.wrapAll( html ); //调用wrapAll(html)为当前元素的所有内容包裹一段HTML代码。
} else {
self.append( html ); //如果当前元素没有内容,则直接将参数html插入当前内容。
}
});
},
})

unwrap的实现如下:

Query.fn.extend({
unwrap: function() { //移除匹配元素集合中每个元素的父标签,并把匹配元素留在父元素的位置上
return this.parent().each(function() { //先遍历父节点
if ( !jQuery.nodeName( this, "body" ) ) { //如果不是body元素
jQuery( this ).replaceWith( this.childNodes ); //则调用replaceWith将this.childNodes替换为this,注意,这里的this上下文是父节点
}
}).end();
}
})

jQuery 源码解析(二十四) DOM操作模块 包裹元素 详解的更多相关文章

  1. jQuery 源码解析(二十五) DOM操作模块 html和text方法的区别

    html和text都可以获取和修改DOM节点里的内容,方法如下: html(value)     ;获取匹配元素集合中的一个元素的innerHTML内容,或者设置每个元素的innerHTML内容,   ...

  2. jQuery 源码解析(二十八) 样式操作模块 scrollLeft和scrollTop详解

    scrollLeft和scrollTop用于获取/设置滚动条的,如下: scrollLeft(val) ;读取或设置整个页面的水平滚动条距离 scrollTop(val) ;读取或设置整个页面的垂直滚 ...

  3. jQuery 源码解析(二十六) 样式操作模块 样式详解

    样式操作模块可用于管理DOM元素的样式.坐标和尺寸,本节讲解一下样式相关,样式操作通过jQuery实例的css方法来实现,该方法有很多的执行方法,如下: css(obj)            ;参数 ...

  4. jQuery 源码解析(二十九) 样式操作模块 尺寸详解

    样式操作模块可用于管理DOM元素的样式.坐标和尺寸,本节讲解一下尺寸这一块 jQuery通过样式操作模块里的尺寸相关的API可以很方便的获取一个元素的宽度.高度,而且可以很方便的区分padding.b ...

  5. jQuery 源码解析(二十二) DOM操作模块 复制元素 详解

    本节说一下DOM操作模块里的复制元素子模块,该模块可以复制一个DOM节点,并且可选择的设置是否复制其数据缓存对象(包含事件信息)和是否深度复制(子孙节点等),API如下: $.clone(elem, ...

  6. jQuery 源码分析(二十) DOM操作模块 插入元素 详解

    jQuery的DOM操作模块封装了DOM模型的insertBefore().appendChild().removeChild().cloneNode().replaceChild()等原生方法.分为 ...

  7. jQuery 源码解析(二十三) DOM操作模块 替换元素 详解

    本节说一下DOM操作模块里的替换元素模块,该模块可将当前匹配的元素替换指定的DOM元素,有两个方法,如下: replaceWith(value)     ;使用提供的新内容来替换匹配元素集合中的每个元 ...

  8. jQuery 源码分析(二十一) DOM操作模块 删除元素 详解

    本节说一下DOM操作模块里的删除元素模块,该模块用于删除DOM里的某个节点,也可以理解为将该节点从DOM树中卸载掉,如果该节点有绑定事件,我们可以选择保留或删除这些事件,删除元素的接口有如下三个: e ...

  9. jquery源码解析:proxy,access,swap,isArraylike详解

    jQuery的工具方法,其实就是静态方法,源码里面就是通过extend方法,把这些工具方法添加给jQuery构造函数的. jQuery.extend({ ...... guid: 1, //唯一标识符 ...

随机推荐

  1. 1篇文章搞清楚8种JVM内存溢出(OOM)的原因和解决方法

    前言 撸Java的同学,多多少少会碰到内存溢出(OOM)的场景,但造成OOM的原因却是多种多样. 堆溢出 这种场景最为常见,报错信息: java.lang.OutOfMemoryError: Java ...

  2. 每天用Mybatis,但是Mybatis的工作原理你真的知道吗?

    近来想写一个mybatis的分页插件,但是在写插件之前肯定要了解一下mybatis具体的工作原理吧,于是边参考别人的博客,边看源码就开干了. 核心部件: SqlSession Executor Sta ...

  3. hdu 1010 Tempter of the Bone(深搜+奇偶剪枝)

    Tempter of the Bone Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Othe ...

  4. 如何"快准狠"找到内存相关的问题

    为了迅速定位内存问题,通常会先运行几个覆盖面比较大的性能工具,比如 free.top.vmstat.pidstat 等. 具体的分析思路主要有这几步 先用 free 和 top,查看系统整体的内存使用 ...

  5. 安装react-native-cli工具(三)

    设置淘宝镜像 (这一步可以省略) npm config set registry https://registry.npm.taobao.org --global npm config set dis ...

  6. CreateDefaultBuilder方法都做了什么?

    当我们创建好一个新的ASP.NET Core Web应用时,系统会使用CreateDefaultBuilder方法,这个方法完成了以下操作: use Kestrel as the web server ...

  7. java之动态代理设计模式

    代理:专门完成代理请求的操作类,是所有动态代理类的父类,通过此类为一个或多个接口动态地生成实现类. 弄清动态代理的关键是清楚java的反射机制,在https://www.cnblogs.com/xix ...

  8. Life is not supposed to be easy 。

    对每个人而言,真正的职责只有一个: 找到自我.然后在心中坚守一生,全心全意,永不停息. 所有其他的路都是不完整的,是人的逃避方式,是对大众理想的懦弱回归,是随波逐流,是对内心的恐惧. 对婚姻,对房子的 ...

  9. Java题库——Chapter15 事件驱动编程和动画

    Chapter 15 Event-Driven Programming and Animations Section 15.2 Events and Event Sources1.    A Java ...

  10. WPF之行为

    Behavior的运用扩展了”交互“功能,以下记录示例: 在的项目中添加两个引用:Microsoft.Expression.Interactions.dllSystem.Windows.Interac ...