本节说一下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. 【Java8流】使用学习

    [Java8流]使用学习 ============================================= 1.删除子目录及文件 ============================== ...

  2. CSS动态表达式

    样式:style:expression(脚本) 如: 1 _top: expression(this.offsetHeight); _top: expression(eval(document.doc ...

  3. TypeScript躬行记(3)——类

    类是对对象的抽象,描述了对象的特征和行为,而对象就是类的实例.ES6引入了类的概念(相关内容可参考ES类和ES6类的继承两节),TypeScript在此基础上,不仅根据ES7等规范完善了类的语法,还添 ...

  4. 上传图片报错-Failed to load resource:the server responded with a status of 413(Request Entity Too Large)

    使用.netcore2.1 做文件上传时,要求是小于20M,上传3至5M都没问题,大于10M,提示错误[如标题],原来是nginx配置的原因 [HttpPost("Postcard" ...

  5. asp.net core react 项目实战(一)

    asp.net-core-react asp.net core react 简介 开发依赖环境 .NET Core SDK (reflecting any global.json): Version: ...

  6. 面试连环炮系列(四):说说TCP的三次握手过程

    说说TCP三次握手的过程? 第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认. 第二次 ...

  7. Centos7 死活上不了网

    NAT模式,手动修改ifcfg 如下: # vi /etc/sysconfig/network-scripts/ifcfg-ens33 TYPE=EthernetPROXY_METHOD=noneBR ...

  8. 字节跳动——IT技术工程师面试题

    .自我介绍 .项目介绍 .争对个人项目进行提问 .场景模拟 .1如何知道用户的指定视频(类似于QQ发视频)的服务是正常的 .使用appum进行自动化测试 .使用bat脚本获取进程状态,然后定时发送em ...

  9. Nginx的安装及配置

    1.概述         Nginx是开源免费的一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器.其特点是占有内存少,并发能力强,使用nginx网站用户有很多,如百 ...

  10. Prism_Composite Commands(3)

    Composite Commands 在许多情况下,视图模型定义的命令将绑定到关联视图中的控件,以便用户可以直接从视图中调用该命令.但是,在某些情况下,您可能希望能够从应用程序UI的父视图中的控件调用 ...