• jQuery 源码解析(二十四) DOM操作模块 包裹元素 详解


    本节说一下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();
        }
    })
  • 相关阅读:
    mongodb修改和删除操作
    mongodb常用查询语句
    ejs常用功能函数
    Rails + React +antd + Redux环境搭建
    nodejs安装和卸载
    Git 建立仓库及常用命令速查表
    使用MVC5+Entity Framework6的Code First模式创建数据库并实现增删改查功能
    gem devise配置
    Ubuntu16.04安装postgresql9.4及pgadmin3图形管理界面
    Rails Migration Data Model栏位修改及数据类型介绍
  • 原文地址:https://www.cnblogs.com/greatdesert/p/11820454.html
Copyright © 2020-2023  润新知