jQuery针对DOM操做的插入的方法有大概10种html
append、prepend、before、after、replaceWithnode
appendTo、prependTo、insertBefore、insertAfter、replaceAllapp
分2组,上下对照,实现一样的功能。主要的不一样是语法——特别是内容和目标的位置dom
依赖的domManip,buildFragment模块在以前就分析过了函数
在匹配元素集合中的每一个元素后面插入参数所指定的内容,做为其兄弟节点ui
对于 .after()
, 选择表达式在函数的前面,参数是将要插入的内容。this
对于.insertAfter()
, 恰好相反,内容在方法前面,它将被放在参数里元素的后面。spa
after: function() { return this.domManip( arguments, function( elem ) { if ( this.parentNode ) { this.parentNode.insertBefore( elem, this.nextSibling ); } }); },
以前提过了全部的方法靠this.domManip合并参数处理,内部经过buildFragment模块构建文档碎片设计
而后把每个方法的具体执行经过回调的方式提供出来处理code
DOM操做并未提供一个直接能够在当前节点后插入一个兄弟节点的方法,可是提供了一个相似的方法
insertBefore() 方法:可在已有的子节点前插入一个新的子节点。语法 :insertBefore(newchild,refchild)
看看jQuery如何处理的
例如
inner.after('<p>Test</p>');
内部就会把 '<p>Test</p>' 经过buildFragment构建出文档elem
而后经过 this.parentNode.insertBefore( elem, this.nextSibling );
这里的this 就是对应着inner ,elem就是‘<p>Test</p>’
看到这里就很好理解了after的实现了
用原生方法简单模拟
var inner = document.getElementsByClassName('inner') for(var i =0 ; i<inner.length;i++){ var elem = inner[i] var div = document.createElement('div') div.innerHTML = 'aaaa' elem.parentNode.insertBefore(div,elem.nextSibling) }
jQuery代码的设计者很聪明的,都尽量的合并类似功能的方法,代码更加精炼美观
jQuery.each({ appendTo: "append", prependTo: "prepend", insertBefore: "before", insertAfter: "after", replaceAll: "replaceWith" }, function( name, original ) { jQuery.fn[ name ] = function( selector ) { }; });
DEMO
$('<p>Test</p>').insertAfter('.inner');
经过$('<p>Test</p>')构建一个文档,对象经过insertAfter方法插入到全部class等于inner的节点后
表达的意思与after是同样的,主要的不一样是语法——特别是内容和目标的位置
jQuery.fn[ name ] = function( selector ) { var elems, ret = [], insert = jQuery( selector ), last = insert.length - 1, i = 0; for ( ; i <= last; i++ ) { elems = i === last ? this : this.clone( true ); jQuery( insert[ i ] )[ original ]( elems ); // Support: QtWebKit // .get() because core_push.apply(_, arraylike) throws core_push.apply( ret, elems.get() ); } return this.pushStack( ret ); };
看具体的实现方法中.insertAfter('.inner');inner其实就被看成selector传入进来了
selector可能只是字符串选择器内部就须要转化,insert = jQuery( selector ),
$('<p>Test</p>')就是构建出来的文档碎片节点,那么若是赋给insert有多个的时候就须要彻底克隆一份副本了,因此就直接赋给
elems = i === last ? this : this.clone( true ); jQuery( insert[ i ] )[ original ]( elems );
依旧是执行after
jQuery( insert[ i ] )[ original ]( elems );
最终还须要返回这个构建的新节点
收集构建的节点
core_push.apply( ret, elems.get() );
构建一个新jQuery对象,以便实现链式
this.pushStack( ret );
可见after 与 insertAfter 本质本质其实都是同样的,只是经过不一样的方式调用
根据参数设定,在匹配元素的前面插入内容
before: function() { return this.domManip( arguments, function( elem ) { if ( this.parentNode ) { this.parentNode.insertBefore( elem, this ); } }); },
相似after只是替换了第二个参数,改变插入的位置
在每一个匹配元素里面的末尾处插入参数内容
append: function() { return this.domManip( arguments, function( elem ) { if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { var target = manipulationTarget( this, elem ); target.appendChild( elem ); } }); },
内部增长节点,直接能够调用appendChild方法
将参数内容插入到每一个匹配元素的前面(元素内部)
prepend: function() { return this.domManip( arguments, function( elem ) { if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { var target = manipulationTarget( this, elem ); target.insertBefore( elem, target.firstChild ); } }); },
相似after只是替换了第二个参数,改变插入的位置
用提供的内容替换集合中全部匹配的元素而且返回被删除元素的集合。
.replaceWith()
能够从DOM中移除内容,而后在这个地方插入新的内容。请看下面的例子:
<div class="container"> <div class="inner first">Hello</div> <div class="inner second">And</div> <div class="inner third">Goodbye</div> </div>
咱们能够用指定的HTML替换第二个 inner <div>
:
$('div.second').replaceWith('<h2>New heading</h2>');
结果以下:
<div class="container"> <div class="inner first">Hello</div> <h2>New heading</h2> <div class="inner third">Goodbye</div> </div>
或者咱们能够选择一个元素把它当作替换的内容:
$('div.third').replaceWith($('.first'));
结果以下:
<div class="container"> <div class="inner second">And</div> <div class="inner first">Hello</div> </div>
从这个例子能够看出,用来替换的元素从老地方移到新位置,而不是复制。
.replaceWith()
方法,和大部分其余jQuery方法同样,返回jQuery对象,因此能够和其余方法连接使用,可是须要注意的是:对于该方法而言,该对象指向已经从 DOM 中被移除的对象,而不是指向替换用的对象。
replaceWith: function() { var // Snapshot the DOM in case .domManip sweeps something relevant into its fragment args = jQuery.map( this, function( elem ) { return [ elem.nextSibling, elem.parentNode ]; }), i = 0; // Make the changes, replacing each context element with the new content this.domManip( arguments, function( elem ) { var next = args[ i++ ], parent = args[ i++ ]; if ( parent ) { // Don't use the snapshot next if it has moved (#13810) if ( next && next.parentNode !== parent ) { next = this.nextSibling; } jQuery( this ).remove(); parent.insertBefore( elem, next ); } // Allow new content to include elements from the context set }, true ); // Force removal if there was no new content (e.g., from empty arguments) return i ? this : this.remove(); },
删除目标节点
jQuery( this ).remove();
而后再插入一个新节点
parent.insertBefore( elem, next );