一、問題概述:
1、隨着jQuery的流行,采用jQuery和$符為命名空間的js庫越來越多,當然jQuery的$符也是參照的Prototype庫的,所以當多個庫同時以$符或者jQuery為命名空間時,那么此時,就會產生沖突。
2、由於jQuery的更新速度過快,所以插件更不上,導致不同版本的jQuery對插件支持的不一樣,而剛好我們此時需要用一個高版本的jQuery進行開發,我們用的z-tree則是低版本的jQuery,所以在這種場景下,則會產生$和jQuery命名空間沖突的問題
3、這里jQuery解決多庫共存的問題的絕決方案只用於單文件js類庫框架,如果是多文件就不行了像EXT這種
二、解決方法
1、通過jQuery自帶的noConflict函數將$或者jQuery映射回給之前使用過$和jQuery對象的js類庫
簡介:jQuery.noConflict()的具體實現
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script> jQuery={};//模擬jQuery對象 //將$和jQuery兩個對象(命名空間)存入到臨時變量中去,應為這兩個變量可能會和其他庫的變量沖突 var _$=window.$,_jQuery=window.jQuery; //上面定義的_$和_jQuery的變量值可能會存在三種情況 //第一種當jQuery文件位於最頂端時,那么里面存儲的就是js全局變量的默認值 //第二種當jQuery文件位於其他js文件之下,且前面的庫庫有使用到window.$和window.jQuery中的任意一個,
//那么當調用下面的noConflict方法之后,jQuery就會將對應的window.$和window.jQuery控制權返還給之前使用到他們的js庫 //實際交還$對象和jQuery對象的方法 jQuery.noConflict=function(deep){ //交還$對象的控制權 //因為jQuery會做window.$=window.jQuery=jQuery這個操作, //將window.$和window.jQuery對象都托管給jQuery對象,所以當 //加載完jQuery文件之后,執行jQuery.noConflict()如果window.$ //對象已經脫管給了jQuery對象的話,那么就通過將原來的 //window.$的值覆蓋現在window.$的形式,完成$對象控制權的交 //換, 所以覆蓋之后的$對象的值就是在jQuery之前使用到$對象的js //庫中定義的值,而我們也不能使用$符來使用選擇器,只能通過jQuery對象 if(window.$===jQuery) { window.$=_$;//將原先緩存的window.$(之前加載完成的js庫的$對象)覆蓋在執行jQuery文件之后重新定義的jQuery自帶的$對象 } //交換jQuery對象的控制權 //jQuery對象不能輕易的交還控制權,所以這里加了一個deep參數,只有當這個參數為true時,才會交還 if(deep && window.jQuery===jQuery) { window.jQuery=_jQuery;//將原先緩存的window.jQuery(之前加載完成的js庫的jQuery對象)覆蓋在執行jQuery文件之后重新定義的jQuery自帶的jQuery對象 }
return jQuery;//返回jQuery對象,這樣的話我們就可以給jQuery對象重新定義一個個性化的名字 } </script> </body> </html>
(1)通過jQuery.noConflict()交還$和jQuery對象的控制權,解決命名控件沖突的問題
當jQuery文件第一個加載時,調用jQuery.noConflict()交換$的控制權
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="../common/jquery-1.9.1.min.js"></script> </head> <body> <script> console.log(window.$);//打印function (e,t){return new b.fn.init(e,t,r)} jQuery中定義的$對象 jQuery.noConflict(); console.log(window.$);//打印出undefined </script> </body> </html>
當jQuery文件在其他js庫加載完之后加載,且這些庫已經使用了$對象
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="../common/prototype.js"></script> <script src="../common/jquery-1.9.1.min.js"></script> </head> <body> <script> console.log(window.$);//打印出:function (e,t){return new b.fn.init(e,t,r)} jQuery中定義的$對象 jQuery.noConflict(); console.log(window.$);//打印出prototype中定義的$對象 </script> </body> </html>
(2)通過jQuery.noConflict()來給jQuery對象重新命名的方式解決沖突問題
這實際上也是交換$對象給前面的js類庫后,通過返回的jQuery對象自定義的給jQuery對象命名的方式,解決的方式其實和上面的是一樣的,但是區別是我們可以定義一個個性化的名字(前提是不要和前面的對象沖突)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="../common/jquery-1.9.1.min.js"></script> </head> <body> <script> var zc=jQuery.noConflict(); alert(zc("body").length);//輸出:1 </script> </body> </html>
(3)聽過jQuery.noConflict()方法返還$對象的控制權,通過匿名執行函數(閉包)的方式重新恢復對$對象的使用,只不過,$對象只在閉包范圍內有效
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="../common/jquery-1.9.1.min.js"></script> </head> <body> <script> jQuery.noConflict();//交還$對象的控制權給前面使用過$對象的js庫 (function($){ alert($("body").length);//輸出:1; })(jQuery)//將jQuery對象作為實參傳遞給形參$,這樣$還是代表jQuery對象 </script> </body> </html>
(4)通過jQuery.noConflict()同時去除$對象和jQuery對象的控制權
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="../common/jquery-1.9.1.min.js"></script> </head> <body> <script> jQuery.noConflict(true); alert($);//輸出:undefined alert(jQuery);//輸出:undefined </script> </body> </html>
(5)下面是終極的解決方案,使用這個方案你可以把jQuery集成到你自己定義的js類庫中區,同時,去除$和jQuery對象的控制,也就是說,$和jQuery不再適用,而把jQuery對象的所有的屬性和方法,都轉移到你的對象下面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="../common/jquery-1.9.1.min.js"></script> </head> <body> <script> var zc={};//自定義的對象 zc.query=jQuery.noConflict(true); alert(zc.query("body").length);//輸出:1 alert(jQuery);//輸出:undefined alert($);//輸出:undefined </script> </body> </html>
通過上面的輸出發現:此時$和jQuery對象均無法使用,而自定義的zc.query怎可以使用jQuery對象所有的屬性和方法