jQueryソース分析のwrap,wrapInner,wrapAll,unwrap方法
8272 ワード
まずeachインスタンスメソッドの使い方を思い出します.
html要素を参照:
<html>
<head>
<script type="text/javascript" src="/jquery/jquery.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("button").click(function(){
$("li").each(function(i,elem){
// each , , DOM
//this DOM !
});
});
});
</script>
</head>
<body>
<button> </button>
<ul>
<li>Coffee</li>
<li>Milk</li>
<li>Soda</li>
</ul>
</body>
</html>
contentsメソッドの使い方をもう一度思い出します:クリックしてリンクを開きますcontents: function( elem ) {
// DOM , iframe contentDocument childNodes NodeList
return jQuery.nodeName( elem, "iframe" ) ?
elem.contentDocument || elem.contentWindow.document :
jQuery.merge( [], elem.childNodes );
}
html要素を参照:
<div class="parent">
<div class="test">
111111
</div>
<div class="test">
22222222
</div>
</div>
<span class="test"></span>
wrapAll源码分析:
结论:(如果调用对象所有DOM元素位置不相邻,那么会把他们移动到第一个匹配元素的位置,然后包裹起来)
我们测试代码如下:
この場合、修正されたhtml構造は以下のようになります.$(document).ready(function() { $('.test').wrapAll("<em style='color:red'><span>Hello you</span></em>"); });
この例では、次の点に注意します.<div class="parent"> <em style="color:red"> <span>Hello you <div class="test"> 111111 </div> <div class="test"> 22222222 </div> <span class="test"></span> </span> </em> </div>
(1)我々の呼び出しオブジェクトはすべて新しく作成されたオブジェクトのサブ要素として現れる.ソースコードに基づいて、最初のステップは私たちが新しく作成したオブジェクトを最初の呼び出しオブジェクトの一番前に置いて、2番目のステップはすべての呼び出しオブジェクトをappendを通じて私たちが新しく作成したオブジェクトの下に入れます!(2)呼び出しオブジェクトのDOM要素はwrapAllを呼び出す前にspan要素はparentの兄弟ノードだったが,呼び出し後はサブノードになったように位置移動する可能性がある.これは,既に存在するノードがDOMの他の位置に挿入されると,そのDOMが元の位置から消えるためである.jQuery.fn.extend({ wrapAll1: function( html ) { // , , DOM // DOM , wrapAll if ( jQuery.isFunction( html ) ) { return this.each(function(i) { jQuery(this).wrapAll( html.call(this, i) ); }); } // DOM if ( this[0] ) { // The elements to wrap the target around // html , jQuery // , DOM , ! ownerDocument ! var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); //alert(wrap.attr("style")); // DOM , id="parent" //insertBefore , //alert(this[0].parentNode.className); if ( this[0].parentNode ) { //wrap jQuery , insertBefore , wrap wrapAll ! wrap.insertBefore( this[0] ); } //alert(this[0].parentNode.innerHTML); .test ! // DOM , , DOM //alert(wrap.attr("style")); //alert(wrap.html()); //alert(wrap[0].outerHTML); //alert(wrap[0].parentNode.outerHTML); $("#result1").html(wrap[0].parentNode.outerHTML); var result=wrap.map(function() { var elem = this; // alert( elem.firstChild); // wrap DOM while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { elem = elem.firstChild; } // wrapAll ! return elem; }); //alert(result.attr("style")); // result wrapAll ! wrapAll result ! //alert(result[0].outerHTML); result.append(this); } return this; } }) //$(".test").wrapAll1("<em style='color:red'></em>"); $(".test").wrapAll1("<em style='color:red'><span>Hello you</span></em>");
wrapInner源码分析:
wrapInner: function( html ) { if ( jQuery.isFunction( html ) ) { return this.each(function(i) { // , DOM // DOM , DOM // wrapInner ! jQuery(this).wrapInner( html.call(this, i) ); }); } return this.each(function() { // DOM jQuery var self = jQuery( this ), // jQuery , iframe contentDocument childNodes contents = self.contents(); // wrapAll , html wrapInner // 。 wrapAll ,wrapInner ! // ! if ( contents.length ) { contents.wrapAll( html ); } else { // append , ! self.append( html ); } }); }
それとも上のHTMLコードなのか、wrapInnerメソッドを呼び出します.この方法を呼び出すとDOM構造は次のようになることが分かった.$(document).ready(function() { $('.test').wrapInner("<em style='color:red'><span>Hello you</span></em>"); });
実際の結果もよく理解されています.wrapInnerでは、最初のステップは呼び出しオブジェクトごとのcontentsを取得し、2番目のステップはwrapAllメソッドを呼び出して、私たちが入力したパラメータでcontentsをすべて包みます.結果は簡単です<div class="parent"> <div class="test"> <em style="color:red"> <span>Hello you 111111 </span> </em> </div> <div class="test"> <em style="color:red"> <span>Hello you 22222222 </span> </em> </div> </div>
つまり、各呼び出しオブジェクトのcontentsはすべて私たちのパラメータオブジェクトに包まれています!
wrapメソッドソース分析:wrap: function( html ) { var isFunction = jQuery.isFunction( html ); return this.each(function(i) { // , wrapAll , jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); }); }
ソースコード解析により,wrapメソッドもwrapAllメソッドを呼び出し,その結果,パラメータは呼び出しオブジェクトの内容ではなく呼び出しオブジェクトごとに包まれることも分かった.また、wrapメソッドを手動で呼び出して、結果を見てみましょう.修正後のhtmlは以下の通りです.$(document).ready(function() { $('.test').wrap("<em style='color:red'><span>Hello you</span></em>"); });
明らかに、wrapメソッドとwrapInnerメソッドの違いは、次のとおりです.<div class="parent"> <em style="color:red"> <span>Hello you <div class="test"> 111111 </div> </span> </em> <em style="color:red"> <span>Hello you <div class="test"> 22222222 </div> </span> </em> </div>
wrapInnerメソッドは各呼び出しオブジェクトの内容をパラメータで包み、wrapメソッドはパラメータで各呼び出しオブジェクトを含む!
unwrapメソッドソース分析:(このメソッドは現在の一致する要素の親要素を除去しますが、内部のサブ要素はすべて保持されますが、body要素は除去されません!)unwrap: function() { // body parents return this.parent().each(function() { if ( !jQuery.nodeName( this, "body" ) ) { // parents DOM jQuery , replaceWith // !, end jQuery( this ).replaceWith( this.childNodes ); } }).end();// end parent , end this, , // end , end
まとめ:
(1)wrapAllはすべての呼び出しオブジェクトをパラメータで包み、最後にすべての呼び出しオブジェクトがパラメータとなる最後のサブ要素に達し、呼び出しオブジェクトが隣接していないと移動します!
(2)wrapInnerはパラメータで各呼び出しオブジェクトのサブ要素(呼び出しオブジェクトはこのパラメータオブジェクトの外層の1層に包まれている)を含み、呼び出しオブジェクトが隣接していなければ移動しない!
(3)wrapは呼び出しパラメータを使用して各呼び出しオブジェクト(サブ要素ではない)を包み、オブジェクトが隣接していなければ移動しない.eachによって1つずつ包まれているからだ.
wrapAll vs wrap:
同じ点:すべて外層で包まれています(wrapは内部でwrapAllを呼び出します)
異なる点:wrapは1つの小包で、wrapAllは一緒に小包です!
注意:wrapInnerだけが小包サブエレメントです!