本节说一下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. tabhost改变标签颜色

    package uiframe.zyx.uiframe.com.uiframe.fragments;import android.os.Bundle;import android.support.an ...

  2. OSU!

    OSU! 首先,由题可知,本题是个期望题,根据期望的套路,定义f[x]为x前的答案,所以最终答案就是f[n] f[x]表示前x期望答案,即每一段的长度立方和的期望(一定要清楚) 但是三次方不好算,由于 ...

  3. sql语句字符串包含

    select instr('1222','122') from dual//前者包含后者>0 oracle mysql 数据库可中 select charindex('1','12') from ...

  4. 安装完PyCharm,启动时弹出Failed to load JVM DLLbinserverjvm

    安装完PyCharm,启动时弹出"Failed to load JVM DLL\bin\server\jvm.dll"解决方案 问题描述:打开PyCharm时,弹出"Fa ...

  5. Redis Cluster 的数据分片机制

    上一篇<分布式数据缓存中的一致性哈希算法> 文章中讲述了一致性哈希算法的基本原理和实现,今天就以 Redis Cluster 为例,详细讲解一下分布式数据缓存中的数据分片,上线下线时数据迁 ...

  6. 使用mongoshake进行oplog同步读取,解决乱码问题

    mongoshake 是个开源的用户mongo数据迁移和同步的工具,支持往各种目标源头写数据 具体:https://github.com/alibaba/MongoShake 有业务场景想把oplog ...

  7. 函数式响应式编程 - Functional Reactive Programming

    我们略过概念,直接看函数式响应式编程解决了什么问题. 从下面这个例子展开: 两个密码输入框,一个提交按钮. 密码.确认密码都填写并一致,允许提交:不一致提示错误. HTML 如下: <input ...

  8. 松软科技Web课堂:JavaScript 正则表达式

    正则表达式是构成搜索模式的字符序列. 该搜索模式可用于文本搜索和文本替换操作. 什么是正则表达式? 正则表达式是构成搜索模式(search pattern)的字符序列. 当您搜索文本中的数据时,您可使 ...

  9. 在mpvue引入flyio

    先来说微信小程序原生的请求接口方式吧,如官网文档,在页面中请求直接调用 在这里感谢接的是提供的免费接口https://blog.csdn.net/c__chao/article/details/785 ...

  10. Sqlite—删除语句(Delete)

    SQLite 的 DELETE 语句用于删除表中已有的记录.可以使用带有 WHERE 子句的 DELETE 查询来删除选定行,否则所有的记录都会被删除. SQLite 要清空表记录,只能使用Delet ...