什么情况下使用到克隆节点?
我们知道在对DOM操作过程中如果直接使用节点会出现节点随操作而变动的情况。比如对节点使用.after/.before/.append等方法后,节点被添加到新的地方,原来的位置上的节点被移除了。有的时候需要保留原来位置上的节点,仅仅是需要一个副本添加到对应位置,这个时候克隆就有了使用场景。
jQuery.fn.clone克隆当前匹配元素集合的一个副本,并以jQuery对象的形式返回。
你还可以指定是否复制这些匹配元素(甚至它们的子元素)的附加数据( data()函数 )和绑定事件。
jQueyr.fn.clone: function( withDataAndEvents, deepDataAndEvents )参数描述
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 ); } }
第四步,保护script计算历史(全局性地标记scripts代码段已经被执行过了),并回收内存,返回克隆节点。
destElements = getAll( clone, "script" ); if ( destElements.length > 0 ) { setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); } destElements = srcElements = node = null; return clone;
b.IE克隆问题汇总fixCloneNodeIssues(src,dest)
src是原节点,dest是src的克隆节点。
IE克隆问题列一下(IE8+)
1.IE6-8当使用cloneNode会克隆事件(这些事件绑定通过attachEvent)。为保证统一性,需要清除克隆的事件,为后续统一克隆事件做准备
// IE6-8当使用cloneNode复制事件(这些事件绑定通过attachEvent)时进入该分支 //清除原来的事件,为克隆事件做准备 if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) { data = jQuery._data( dest ); for ( e in data.events ) { jQuery.removeEvent( dest, e, data.handle ); } dest.removeAttribute( jQuery.expando ); }
2.IE8-克隆脚本标签script的时候克隆的内容结果会是空白。我们需要给他重新赋值,并确保他不会执行脚本内容。
//IE克隆脚本时内容为空白,并试图执行新设置的文本 if ( nodeName === "script" && dest.text !== src.text ) { disableScript( dest ).text = src.text; restoreScript( dest ); }
3.IE6-10不能克隆使用的classid获取的对象元素的子节点。IE10下,如果父节点为null,则会抛出NoModificationAllowedError异常。需要使用原节点的outerHTML和innerHTML重新赋值。
//IE6-10不能克隆使用的classid获取的对象元素的子节点。 //IE10下,如果父节点为null,则会抛出NoModificationAllowedError异常 else if ( nodeName === "object" ) { if ( dest.parentNode ) { dest.outerHTML = src.outerHTML; } //对于IE9,这个条分支不可避免。 //IE9中克隆对象元素,上述outerHTML策略是不充分的。 //如果src具有的innerHTML并且克隆节点却没有, //复制src.innerHTML到dest.innerHTML #10324 if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) { dest.innerHTML = src.innerHTML; } }
4.IE6-8无法克隆一个复选框或单选按钮的选中状态。需要主动设置。
// manipulation_rcheckableType = /^(?:checkbox|radio)$/i else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) { //IE6-8无法坚持一个克隆的复选框或单选按钮的选中状态 //更糟的是,如果defaultChecked值没有设置,则IE6-7无法给克隆元素选中状态的外观 dest.defaultChecked = dest.checked = src.checked; ... }
5.当克隆select标签时,IE6-8无法正确返回select默认选中状态。需要主动设置。
//当克隆选项时,IE6-8无法正确返回select默认选中状态 else if ( nodeName === "option" ) { dest.defaultSelected = dest.selected = src.defaultSelected; }
6.当克隆其他类型的input和textare标签时,IE6-8不能正确设置defaultValue为正确的值。需要主动设置。
//当克隆其他类型的input标签时,IE6-8不能正确设置defaultValue为正确的值 else if ( nodeName === "input" || nodeName === "textarea" ) { dest.defaultValue = src.defaultValue; }
里面用到disableScript这个函数。函数目的是改变script的type,从而保证在给script赋值后不会被作为脚本执行。这个方式我们可以借鉴
//为安全DOM操作替换/保存script节点元素type属性 function disableScript( elem ) { var attr = elem.getAttributeNode("type"); elem.type = ( attr && attr.specified ) + "/" + elem.type; return elem; }
以上内容是小编给大家介绍的关于jQuery-1.9.1源码分析系列(十一)DOM操作续之克隆节点的全部叙述,希望大家喜欢。
本文向大家介绍Jquery 1.9.1源码分析系列(十二)之筛选操作,包括了Jquery 1.9.1源码分析系列(十二)之筛选操作的使用技巧和注意事项,需要的朋友参考一下 废话不多说了直接奔入主题了。 find接受一个参数表达式selector:选择器(字符串)、DOM元素(Element)、jQuery对象。分两种情况处理: 第一种,如果传入的参数是非字符串,则先通过jQuery选择器将
本文向大家介绍jQuery 1.9.1源码分析系列(十三)之位置大小操作,包括了jQuery 1.9.1源码分析系列(十三)之位置大小操作的使用技巧和注意事项,需要的朋友参考一下 先给大家展示谢 jQuery.fn.css (propertyName [, value ]| object )(函数用于设置或返回当前jQuery对象所匹配的元素的css样式属性值。如果需要删除指定的css属性,请使用
本文向大家介绍jQuery 1.9.1源码分析系列(十四)之常用jQuery工具,包括了jQuery 1.9.1源码分析系列(十四)之常用jQuery工具的使用技巧和注意事项,需要的朋友参考一下 为了给下一章分析动画处理做准备,先来看一下一些工具。其中队列工具在动画处理中被经常使用。 jQuery.fn. queue(([ queueName ] [, newQueue ]) || ([ queu
本文向大家介绍jQuery 1.9.1源码分析系列(十)事件系统之绑定事件,包括了jQuery 1.9.1源码分析系列(十)事件系统之绑定事件的使用技巧和注意事项,需要的朋友参考一下 事件绑定的方法有很多种,使用了jquery那么原理那种绑定方式(elem.click = function(){...}))就不太想推荐给大家了。最主要的原因是elem.click=fn这种方式只能绑定一个事件处理,
本文向大家介绍jQuery 1.9.1源码分析系列(十五)动画处理之缓动动画核心Tween,包括了jQuery 1.9.1源码分析系列(十五)动画处理之缓动动画核心Tween的使用技巧和注意事项,需要的朋友参考一下 在jQuery内部函数Animation中调用到了createTweens()来创建缓动动画组,创建完成后的结果为: 可以看到上面的缓动动画组有四个原子动画组成。每一个原子动画的信
在本章中,我们将讨论学习XML DOM对象上的克隆节点操作。 克隆节点操作用于创建指定节点的副本。 方法用于此操作。 cloneNode()方法 此方法返回此节点的副本,即用作节点的通用副本构造函数。 重复节点没有父节点(为),没有用户数据。 语法 方法具有以下语法 - - 如果为,则递归克隆指定节点下的子树; 如果为,则仅克隆节点本身及其属性(如果它是元素的话)。 此方法返回重复节点。 示例 以
本文向大家介绍jQuery1.9.1源码分析系列(十六)ajax之ajax框架,包括了jQuery1.9.1源码分析系列(十六)ajax之ajax框架的使用技巧和注意事项,需要的朋友参考一下 AJAX 简介 AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。 您应当具备的基础知识 在继续学习之前,您需要对下面的知识有基本的了解: HTML / XHTML CSS JavaSc
本文向大家介绍jQuery中DOM操作实例分析,包括了jQuery中DOM操作实例分析的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了jQuery中DOM操作的方法。分享给大家供大家参考。具体分析如下: 这里主要设计的dom操作包括:dom对象的创建(JS方式和jquery方式)、属性的修改、样式的修改、动态绑定事件 代码如下: 希望本文所述对大家的jQuery程序设计有所帮助。