しかし、よく見ると、すべてが美しいとは限りません。 jQueryは、ブラウザーによってロードされているかどうかに関係なく、ネストされた各ライブラリーをロードし、さらにブラウザーキャッシュの使用を防ぐためにクエリに一意のパラメーターを追加します。 jQuery開発者がこの特定のスキームを選択し、この問題を修正するhtml()関数をラップする理由については詳しく説明しませんでした。
だから。 どのような問題を解決する必要がありますか:
1.ライブラリとスタイルをリロードしないでください
2.新しいライブラリまたはスタイルをロードするときは、ブラウザーのキャッシュを使用します
3.ネストされたスクリプトは接続されたライブラリの関数を使用できるため、すべてのライブラリをロードした後に実行する必要があります。
原則として、複雑なことは何もありません。 この問題は、正規表現を使用して解決されます。
1.コンテンツからすべての<script>および<link>タグを切り取り、既に接続されているタグと比較し、状況に応じてそれらをロードします。
2.ネストされたすべてのスクリプトを実行する接続ライブラリのonloadイベントハンドラを配置します。
プラグイン自体のコードを同封します。
(function($){ var originalHtmlMethod = $.fn.html; /** * */ var sanitize = { scriptsCountLoading:0, inlineScripts:[], /** * onload. * */ loadingCompleted:function(){ if (this.scriptsCountLoading==0){ if ($.isArray(this.inlineScripts)){ for (var i=0; i<this.inlineScripts.length; i++){ eval.call(window,this.inlineScripts[i]); } this.inlineScripts = []; }else{ if (this.inlineScripts){ eval.call(window,this.inlineScripts); this.inlineScripts = []; } } } }, /** * javascript . * scriptsCountLoading */ sanitizeScripts:function(data){ var scripts = $('script'); var scriptSrc = []; for (var i=0; i<scripts.length; i++){ scriptSrc[scriptSrc.length] = scripts[i].src; } var patternScripts = /<script[^<>]*?src=\"?([^><\\\"\\']*)\"?[^<>]*?>[\s\S]*?<\/script>/igm; var absolutePath = /https?:\/\//; var matches = null; var dataScriptSrc = {}; while (matches = patternScripts.exec(data)){ var matchedString = matches[0]; var src = matches[1]; if (absolutePath.test(src)){ // absolute path }else{ // relative path if (src[0]!='/'){ src = window.location.href.replace(/#|\?.*$/)+'/'+src; var m = null; while (m = /[^\/]*\/\.\.\//ig.exec(src)){ src = src.replace(m[0],''); } }else{ src = window.location.protocol+'//'+window.location.hostname+src; } } data = data.replace(matchedString,''); patternScripts.lastIndex -= matchedString.length; if ($.inArray(src,scriptSrc)==-1){ this.scriptsCountLoading++; // var self = this; this.loadScript(src,function(){ self.scriptsCountLoading--; self.loadingCompleted(); }); } } return data; }, /** * . */ sanitizeInlineScripts:function(data){ var scripts = $('script'); var scriptSrc = []; for (var i=0; i<scripts.length; i++){ scriptSrc[scriptSrc.length] = scripts[i].src; } var patternScripts = /<script[^<>]*?>([\s\S]*?)<\/script>/igm; var absolutePath = /https?:\/\//; var matches = null; var dataScriptSrc = {}; while (matches = patternScripts.exec(data)){ var matchedString = matches[0]; var script = matches[1]; data = data.replace(matchedString,''); patternScripts.lastIndex -= matchedString.length; this.inlineScripts[this.inlineScripts.length] = script } return data; }, /** * css , */ sanitizeHeadLinks:function(data){ var links = $('link'); var linkSrc = []; for (var i=0; i<links.length; i++){ linkSrc[linkSrc.length] = links[i].href; } var patternHeadLinks = /<link[^<>]*?href=\"?([^><\\\"\\']*)\"?[^<>]*?\/>/igm; var absolutePath = /https?:\/\//; var matches = null; var dataScriptSrc = {}; while (matches = patternHeadLinks.exec(data)){ var matchedString = matches[0]; var src = matches[1]; if (absolutePath.test(src)){ // absolute path }else{ // relative path if (src[0]!='/'){ src = window.location.href.replace(/#|\?.*$/)+'/'+src; var m = null; while (m = /[^\/]*\/\.\.\//ig.exec(src)){ src = src.replace(m[0],''); } }else{ src = window.location.protocol+'//'+window.location.hostname+src; } } data = data.replace(matchedString,''); patternHeadLinks.lastIndex -= matchedString.length; if ($.inArray(src,linkSrc)==-1){ this.loadCSS(src); } } return data; }, /** * */ sanitizeData:function(data){ data = this.sanitizeInlineScripts(this.sanitizeScripts(this.sanitizeHeadLinks(data))); return data; }, /** * */ loadScript:function(url,onload){ var e = document.createElement("script"); e.src = url; e.type="text/javascript"; if (onload instanceof Function){ e.onreadystatechange= function () { if (this.readyState == 'complete') onload(); } e.onload= onload; } document.getElementsByTagName("head")[0].appendChild(e); }, /** * css */ loadCSS:function(url){ var oLink = document.createElement("link") oLink.href = url; oLink.rel = "stylesheet"; oLink.type = "text/css"; document.getElementsByTagName("head")[0].appendChild(oLink); } } /** * html() */ $.fn.html = function(data){ data = sanitize.sanitizeData(data); var res = originalHtmlMethod.apply( this, [data] ); sanitize.loadingCompleted(); return res; } })(jQuery);
Upd:ハブロフスク市民の反応を考慮して、私はいくつかの説明を加える必要があると思います。
この投稿は、特定のPCPフレームワークの使用に起因する(アーキテクチャを変更せずに)問題をすばやく解決するためのアイデアまたはオプションとして作成されました。 この場合、彼はYiiのアーキテクチャに導かれました。
プラグインはスクリプトの自己完結型パッケージであるため、すべてが奇跡的に機能し始めたら、「プラグイン」するだけで十分です。 この場合、プラグイン自体が必要なすべてのライブラリ、スクリプト、スタイルを追加し、フレームワークがこのすべてを結論に送ります。
多くのプラグインはコンテンツを動的にロードし(ajaxom)、ここで問題が発生します。 この動的コンテンツには、Yiiツール(すべてのライブラリ、スクリプト、およびスタイル)に接続された自己完結型のプラグインが含まれている場合があります。 そのようなコンテンツをロードするとき、jQueryは上記のように動作します。 これらのプラグインはjQueryを使用するため、グローバルな露出のためにhtml()関数をオーバーロードすることを提案することは論理的でした。
一般に、html()関数自体の変更は基本的ではありません。 最初のコメントで述べたように、事前定義されたdataFilterを使用することもできます。