3

サイトにドロップするコードのスニペットで構成されるウィジェットを作成しています。このウィジェットは、js を介してコンテンツを取り込みます。スニペットの例を次に示します。

<div data-token="bc1cea6304e8" id="my-widget">
    <script src="http://localhost:8080/assets/eg-widget.js" type="text/javascript"></script>
</div>

ページに既に jQuery があるかどうかを確認するテストを行っています。ある場合は、バージョンが少なくとも 1.5​​ であることを確認します。

if (typeof jQuery == 'undefined' || isVersion("1.5", ">")) {

    var script_tag = document.createElement('script');
    script_tag.setAttribute("type", "text/javascript");
    script_tag.setAttribute("src",
        "http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js");

    // Try to find the head, otherwise default to the documentElement
    (document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script_tag);

    if (script_tag.readyState) {
        script_tag.onreadystatechange = function () { // For old versions of IE
            if (this.readyState == 'complete' || this.readyState == 'loaded') {
                scriptLoadHandler();
            }
        };
    } else { // Other browsers
        script_tag.onload = scriptLoadHandler;
    }
} else {
    // The jQuery version on the window is the one we want to use
    jQueryEg = window.jQuery;
    scriptLoadHandler();
}

いずれの場合も、使用することにした jQuery に変数 jQueryEg を設定して、競合を回避できるようにします。

jQuery がまだ読み込まれていない場合は、すべて問題ありません。ただし、古いバージョンがロードされている場合、jQuery-ui などの他のライブラリをロードしようとすると競合が発生します。

これを行うには、window.jQuery を新しくロードした jQuery に設定して、jquery-ui と bootstrap.js をロードするときに、window.jQuery または $ への参照が正しいバージョンを指すようにします。

問題は、window.jQuery を私たちのバージョンに設定したのと同時に、ページの他の部分が jQuery を呼び出すことがあり、それが問題を引き起こすことです。

これらの競合を回避する方法について何か考えはありますか?

jQueryEg = window.jQuery.noConflict(true);
window.jQueryEg = jQueryEg;

// jquery-ui reference window.jQuery so we need to set that to our new jquery for a sec

if (jQueryEg.ui == undefined || jQueryEg.ui.datepicker == undefined) {
    var otherjQuery = window.jQuery;
    window.jQuery = jQueryEg;

    var script_tag = document.createElement('script');
    script_tag.setAttribute("type", "text/javascript");
    script_tag.setAttribute("src",
        "//ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min.js");
    (document.getElementsByTagName("head")[0] || document.documentElement).appendChild(script_tag);

    script_tag.onload = function () {
        window.jQuery = otherjQuery;
        main();
    };

}
4

2 に答える 2

5

同様の問題に遭遇したら。jQuery-UI コードを見ると、すべてがすぐに呼び出される関数式でラップされていることに気付きました (または、自分でラップしたのでしょうか? 思い出せません)。

( function ( jQuery, undefined ){
  // Code here...
})( jQuery );

プライベート スコープを作成します。だから私の解決策は

  1. 現在の保存jQueryjQuery_OLD
  2. 新しい jQuery バージョンをロードする
  3. jQuery-UI をロードし、互換性のあるバージョンを取得します
  4. 古い復元jQuery

したがって、次のアイデアが得られます

<script src="jquery-1.4.js"></script>
<script>
    var jQuery_1_4 = jQuery.noConflict();
</script>
<script src="jquery-1.8.js"> </script>
<!-- load jquery UI -->
<script src="jquery-ui.js"> </script>
<!-- restore window.jQuery -->
<script>
    jQuery = jQuery_1_4;
</script>
于 2012-09-29T17:38:39.843 に答える
1

以前にこの正確な状況に遭遇したことがありますが、最終的には、おそらくあなたがすでに知っていることであり、聞きたくないことでした.そのような外部ライブラリの複数のバージョンをロードするときに、すべてのエッジケースを回避する良い方法はありません.既に指定した理由によります。関連する合併症の概要は次のとおりです。

  • もちろん、主な問題は、外部スクリプトの読み込みがその性質上非同期であり、すべてが適切にラップされるようにするための「実行直前」/「実行直後」のコールバックがないことです。つまり、動的にロードされるコードを「囲む」方法はありません。
  • スクリプトは、ドキュメントに直接配置すると順番に実行されますが、別のスクリプトによって決定されたものに基づいて条件付きでロードする方法はありません。
  • 最後に、使いやすさの理由から (つまり、コードの知識がなく、サポート スタッフもいない状態で、Web 上のランダムな人々があなたのスニペットを使用できるようにするため)、「このスニペットを他のスクリプトより前に貼り付けてください!」などの制限があります。です。それらが機能したとしても (*他の 2 つの点を実際に確認することはありません)、特にページを完全に制御できない人からは無視されます。

残念ながら、唯一の答えは明らかです。独自のサーバーでライブラリの変更されたバージョンをホストします。

もちろん、これらのバージョンを常に提供する必要はないので、Google の CDN を使用するメリットは引き続きあります。その間、独自の CDN を使用して変更されたバージョンを配信することもできます。従うべき主なガイドラインは次のとおりです。

  1. ページ全体が読み込まれた後に (onDOMReady などを使用して) スクリプトを実行し、独自のスクリプトが含まれた「後」に競合が発生しないようにします。
  2. 競合が発生する可能性があるかどうかを判断します。そのような場合は変更したバージョンを提供し、それ以外の場合はパブリック CDN から提供します。
  3. 他のライブラリとの互換性を頻繁に確認してください。使用するライブラリと同じように、コードは時間の経過とともに進化します。これが機能するには、「競合が可能かどうかを判断する」ステップが正確である必要があります。注意が必要です。確信が持てない場合は、独自のバージョンを提供してください。
  4. 何らかの形で検出が失敗した場合に備えて、「常に変更されたバージョンを使用する」と言う簡単なオプションを常に提供してください。
  5. サーバーの負荷を軽減するために、適切なキャッシュ ヘッダーを使用して、スクリプトの圧縮された醜いバージョンを常に提供してください。

通常、自分のサーバーでのヒット数は実際には比較的少ないことがわかります。いつものように、私を信用しないでください。自分自身の現実世界のシナリオについて統計をとってください!

于 2012-09-29T17:43:56.587 に答える