Rumah > Artikel > hujung hadapan web > jQuery-1.9.1 Siri Analisis Kod Sumber (11) Operasi DOM Diteruskan Pengklonan Nodes_jquery
Bilakah nod klon digunakan?
Kami tahu bahawa jika nod digunakan secara langsung semasa operasi DOM, nod akan berubah dengan operasi. Contohnya, selepas menggunakan .after/.before/.append dan kaedah lain pada nod, nod ditambah ke lokasi baharu dan nod di lokasi asal dialih keluar. Kadangkala nod perlu dikekalkan di lokasi asalnya dan hanya perlu menambah salinan ke lokasi yang sepadan Dalam kes ini, pengklonan mempunyai kes penggunaan.
jQuery.fn.clone mengklonkan salinan set elemen padanan semasa dan mengembalikannya sebagai objek jQuery.
Anda juga boleh menentukan sama ada hendak menyalin data tambahan (fungsi data()) dan peristiwa terikat unsur padanan ini (walaupun anak mereka).
jQueyr.fn.clone: fungsi(denganDataAndEvents, deepDataAndEvents) perihalan parameter
a. Langkah pelaksanaan asas fungsi klon dipecahkan seperti berikut (jQuery.clone)
Langkah pertama ialah mengklonkan nod DOM. Gunakan cloneNode(true) secara langsung untuk nod DOM yang menyokong pengklonan nod yang betul (iaitu, menyokong elem.cloneNode dan memastikan pengklonan yang betul), jika tidak, bina nod untuk menyimpan data yang diklon dan kemudian dapatkan nod tersebut.
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 ); }
Dalam langkah kedua, jika anda menggunakan pelayar IE, anda perlu membetulkan isu pengklonan IE satu demi satu melalui fixCloneNodeIssues( nod, destElements[i] );. Semua penyelesaian pengklonan IE disertakan dalam fixCloneNodeIssues, yang akan dianalisis secara terperinci dalam bahagian seterusnya. Klik di sini untuk melihat lebih banyak kandungan 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] ); } } }
Langkah ketiga, jika anda ingin mengklon data cache (termasuk data biasa dan peristiwa mengikat), klonkannya.
//克隆绑定的事件 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 ); } }
Nota: Fungsi cloneCopyEvent akan menyimpan data nod asal ke nod klon, dan kemudian mengikat peristiwa nod asal kepada nod klon baharu
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 ); } }
Langkah keempat ialah untuk melindungi sejarah pengiraan skrip (menandai secara global segmen kod skrip sebagai telah dilaksanakan), menuntut semula memori dan kembali ke nod klon.
destElements = getAll( clone, "script" ); if ( destElements.length > 0 ) { setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); } destElements = srcElements = node = null; return clone;
b. Ringkasan isu pengklonan IE fixCloneNodeIssues(src,dest)
src ialah nod asal, dan dest ialah nod klon src.
Senaraikan masalah pengklonan IE (IE8)
1.IE6-8 akan mengklon acara apabila menggunakan cloneNode (acara ini terikat melalui attachEvent). Untuk memastikan keseragaman, adalah perlu untuk mengosongkan acara klon dan bersedia untuk acara pengklonan bersatu berikutnya
// 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-Apabila mengklon skrip tag skrip, kandungan yang diklon akan kosong. Kami perlu menetapkannya semula dan memastikan ia tidak melaksanakan kandungan skrip.
//IE克隆脚本时内容为空白,并试图执行新设置的文本 if ( nodeName === "script" && dest.text !== src.text ) { disableScript( dest ).text = src.text; restoreScript( dest ); }
3.IE6-10 tidak boleh mengklon nod anak bagi elemen objek yang diperoleh menggunakan classid. Di bawah IE10, jika nod induk adalah batal, pengecualian NoModificationAllowedError akan dibuang. Ia adalah perlu untuk menetapkan semula outerHTML dan innerHTML nod asal.
//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 tidak boleh mengklon keadaan pilihan kotak semak atau butang radio. Memerlukan tetapan aktif.
// 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. Apabila mengklon teg pilih, IE6-8 tidak boleh kembali dengan betul kepada keadaan pilihan lalai pilih. Memerlukan tetapan aktif.
//当克隆选项时,IE6-8无法正确返回select默认选中状态 else if ( nodeName === "option" ) { dest.defaultSelected = dest.selected = src.defaultSelected; }
6. Apabila mengklonkan jenis input dan teg teks yang lain, IE6-8 tidak boleh menetapkan nilai lalai dengan betul kepada nilai yang betul. Memerlukan tetapan aktif.
//当克隆其他类型的input标签时,IE6-8不能正确设置defaultValue为正确的值 else if ( nodeName === "input" || nodeName === "textarea" ) { dest.defaultValue = src.defaultValue; }
Fungsi disableScript digunakan di dalam. Tujuan fungsi adalah untuk menukar jenis skrip untuk memastikan ia tidak akan dilaksanakan sebagai skrip selepas memberikan nilai kepada skrip. Kita boleh belajar daripada pendekatan ini
//为安全DOM操作替换/保存script节点元素type属性 function disableScript( elem ) { var attr = elem.getAttributeNode("type"); elem.type = ( attr && attr.specified ) + "/" + elem.type; return elem; }
Kandungan di atas ialah keseluruhan perihalan siri analisis kod sumber jQuery-1.9.1 (11) kesinambungan operasi DOM nod pengklonan yang diperkenalkan oleh editor saya harap anda menyukainya.