1.9.1源码分析系列(十一)之DOM操作(2)

if ( hasScripts ) { doc = scripts[ scripts.length - 1 ].ownerDocument; // Reenable scripts jQuery.map( scripts, restoreScript ); //在第一个文档插入使执行可执行脚本 for ( i = 0; i < hasScripts; i++ ) { node = scripts[ i ]; if ( rscriptType.test( node.type || "" ) && !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) { if ( node.src ) { // Hope ajax is available... jQuery.ajax({ url: node.src, type: "GET", dataType: "script", async: false, global: false, "throws": true }); } else { jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) ); } } } }

b. dom操作拓展

jQuery.fn.text

jQuery.fn.text: function( value ) { return jQuery.access( this, function( value ) { return value === undefined ? jQuery.text( this ) : this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); }, null, value, arguments.length ); }

  最终执行value === undefined ? jQuery.text( this ) : this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );

  其中jQuery.text = Sizzle.getText;

jQuery.fn.html

  函数使用jQuery.access来处理

jQuery.fn.html: function( value ) { return jQuery.access( this, function( value ) {...}, null, value, arguments.length ); }

  如果没有参数表示是取值

if ( value === undefined ) { return elem.nodeType === 1 ? elem.innerHTML.replace( rinlinejQuery, "" ) : undefined; }

  否则看是否能用innerHTML添加内容。点击参考兼容问题

//看看我们是否可以走了一条捷径,只需使用的innerHTML //需要执行的代码script|style|link等不能使用innerHTML //htmlSerialize:确保link节点能使用innerHTML正确序列化,这就需要在IE浏览器的包装元素 //leadingWhitespace:IE strips使用.innerHTML需要以空白开头 //不是需要额外添加结束标签或外围包装标签的元素 if ( typeof value === "string" && !rnoInnerhtml.test( value ) && ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) && ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) { value = value.replace( rxhtmlTag, "<$1></$2>" ); try { for (; i < l; i++ ) { //移除元素节点和缓存,阻止内存泄漏 elem = this[i] || {}; if ( elem.nodeType === 1 ) { jQuery.cleanData( getAll( elem, false ) ); elem.innerHTML = value; } } elem = 0; //如果使用innerHTML抛出异常,使用备用方法 } catch(e) {} }

  如果不能使用innerHTML或使用不成功(抛出异常),则使用备用方法append

//备用方法,使用append添加节点 if ( elem ) { this.empty().append( value ); }    jQuery.fn.wrapAll(用单个标签将所有匹配元素包裹起来)   处理步骤:   传入参数是函数则将函数结果传入 if ( jQuery.isFunction( html ) ) {   return this.each(function(i) {     jQuery(this).wrapAll( html.call(this, i) );   }); }   创建包裹层 //获得包裹标签 The elements to wrap the target around var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); if ( this[0].parentNode ) {   wrap.insertBefore( this[0] ); }

  用包裹裹住当前jQuery对象

wrap.map(function() {   var elem = this;   while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {     elem = elem.firstChild;   }   return elem; }).append( this );

  注意:当前jQuery对象匹配的元素最好只有一个,如果有多个的话不推荐使用,这种情况慎用,后面举例可以看到。

  简单的例子,原DOM为(后面都使用这个例子)

<div> <div> <input type='submit'> </div> </div> <div>我是right</div>   $('#center').wrapAll("<p></p>")后,dom变成了 <p>   <div>     <div>       <input type="submit">     </div>   </div> </p> <div>我是right</div>

  慎用:如果当前jQuery所匹配的元素不止一个,例如原DOM执行$('div').wrapAll(“<p></p>”)后结果DOM变成

<p>   <div></div>   <div> <input type="submit"> </div>   <div>我是right</div> </p>

  看到结果了吧,本来#center是#ss的父节点,结果变成了#ss的兄弟节点。

jQuery.fn.wrapInner(在每个匹配元素的所有子节点外部包裹指定的HTML结构)

  处理步骤:

  传入参数是函数则将函数结果传入

if ( jQuery.isFunction( html ) ) { return this.each(function(i) { jQuery(this).wrapInner( html.call(this, i) ); }); }

  遍历jQuery对象数组,获取每个元素包含的内容(所有子节点)contents,然后使用warpAll包裹住contents

return this.each(function() { var self = jQuery( this ), contents = self.contents(); if ( contents.length ) { contents.wrapAll( html ); } else { self.append( html ); } });

  还是使用上面的例子中的原DOM,执行$('div').wrapInner('<p></p>')后结果DOM变成

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wgzdsg.html