首页 > 网站 > WEB开发 > 正文

jQuery-1.9.1源码分析系列(十一)DOM操作续——克隆节点

2024-04-27 15:02:56
字体:
来源:转载
供稿:网友

  什么情况下使用到克隆节点?

  我们知道在对DOM操作过程中如果直接使用节点会出现节点随操作而变动的情况。比如对节点使用.after/.before/.append等方法后,节点被添加到新的地方,原来的位置上的节点被移除了。有的时候需要保留原来位置上的节点,仅仅是需要一个副本添加到对应位置,这个时候克隆就有了使用场景。

 

  jQuery.fn.clone克隆当前匹配元素集合的一个副本,并以jQuery对象的形式返回。

  你还可以指定是否复制这些匹配元素(甚至它们的子元素)的附加数据( data()函数 )和绑定事件。

  jQueyr.fn.clone: function( withDataAndEvents, deepDataAndEvents )参数描述

withDataAndEvents

可选/Boolean类型,是否同时复制元素的附加数据和绑定事件,默认为false。

deepWithDataAndEvents

可选/Boolean类型,是否同时复制元素的所有子元素的附加数据和绑定事件,默认值即为参数withDataAndEvents的值。

  

a.克隆函数的底层实现步骤分解如下(jQuery.clone)


  第一步,先克隆出DOM节点。对支持正确的节点克隆(即支持elem.cloneNode并保证克隆无误)的DOM节点直接使用cloneNode(true),否则自建一个节点来保存被克隆数据然后获取该节点。

if ( jQuery.support.html5Clone || jQuery.isxmlDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {    clone = elem.cloneNode( true );// IE<=8 不能正确克隆已分离、未知的节点//直接新建一个相同的节点,然后获取} else {
  //fragmentDiv是全局变量 fragmentDiv.innerHTML
= elem.outerHTML; fragmentDiv.removeChild( clone = fragmentDiv.firstChild );}

  第二步,如果是IE浏览器下,则需要通过fixCloneNodeIssues( node, destElements[i] );来逐个修正IE克隆问题。IE克隆解决方案全部包含在了fixCloneNodeIssues中,下一节详细分析。里面的jQuery.support内容点击这里查看更多

//针对ie克隆问题修正if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&    (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {    //在这里我们不使用Sizzle的原因是: http://jsperf.com/getall-vs-sizzle/2    destElements = getAll( clone );    srcElements = getAll( elem );    //修正所有IE克隆问题    for ( i = 0; (node = srcElements[i]) != null; ++i ) {        // Ensure that the destination node is not null; Fixes #9587        if ( destElements[i] ) {            fixCloneNodeIssues( node, destElements[i] );        }    }}

   第三步,如果要克隆缓存数据(包括普通数据和绑定事件),克隆之

//克隆绑定的事件if ( dataAndEvents ) {    if ( deepDataAndEvents ) {        srcElements = srcElements || getAll( elem );        destElements = destElements || getAll( clone );        for ( i = 0; (node = srcElements[i]) != null; i++ ) {            cloneCopyEvent( node, destElements[i] );        }    } else {        cloneCopyEvent( elem, clone );    }}

  备注:cloneCopyEvent函数中会将原节点的数据保存到克隆节点中,然后将原节点的事件绑定到新的克隆节点上

    function cloneCopyEvent( src, dest ) {        if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {            return;        }        var type, i, l,        oldData = jQuery._data( src ),        curData = jQuery._data( dest, oldData ),//dest是克隆对的节点        events = oldData.events;        if ( events ) {            //保证被克隆的节点的事件对象干净,确保没有后面添加的事件没有重复            delete curData.handle;            curData.events = {};            for ( type in events ) {                for ( i = 0, l = events[ type ].length; i < l; i++ ) {                    jQuery.event.add( dest, type, events[ type ][ i ] );                }            }        }        // 使克隆的数据对象化        if ( curData.data ) {            curData.data = jQuery.extend( {}, curData.data );        }    }
View Code
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表