2 Stimmen

Verwendung von getScript zum Importieren von Plugins auf einer Seite, die mehrere Versionen von jQuery verwendet

Ich entwickle eine App auf einer Seite, die jQuery 1.2.6 verwendet, aber ich würde gerne jQuery 1.4.2 für meine App verwenden. Ich mag es wirklich nicht, mehrere Versionen von jQuery wie diese zu verwenden, aber die Kopie auf der Seite (1.2.6) ist etwas, das ich nicht kontrollieren kann. Ich habe beschlossen, meinen Code wie folgt zu isolieren:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<script type="text/javascript" src="jquery-1.2.6.min.js>
<script type="text/javascript" src="pageStuff.js"></script>
</head>
<body>
Welcome to our page.
<div id="app">
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
    <script type="text/javascript" src="myStuff.js"></script>
</div>
</body></html>

Die Datei myStuff.js enthält meinen eigenen Code, der jQuery 1.4.2 verwenden soll, und er sieht wie folgt aus:

(function($) {  //wrap everything in function to add ability to use $ var with noConflict
    var jQuery = $;
    //my code
})(jQuery.noConflict(true));

Dies ist eine stark vereinfachte Version, aber ich hoffe, Sie können sich vorstellen, was ich gemacht habe. Eine Zeit lang funktionierte alles gut. Ich beschloss jedoch, ein jQuery-Plugin in einer separaten Datei zu verwenden. Ich testete es und es verhielt sich komisch. Nach einigen Experimenten fand ich heraus, dass das Plugin die alte Version von jQuery verwendet, obwohl ich wollte, dass es die neue Version verwendet. Weiß jemand, wie man eine js-Datei aus dem Kontext innerhalb der Funktion, die den Code in myStuff.js umhüllt, importieren und ausführen kann?

Falls es jemanden interessiert, hier ist, woher ich weiß, dass das Plugin die alte Version verwendet, und was ich getan habe, um das Problem zu lösen: Ich habe eine Datei namens test.js erstellt, die aus dieser Zeile besteht:

alert($.fn.jquery);

Ich habe versucht, die Datei in einem Skript-Tag zu referenzieren, so wie externes Javascript normalerweise eingebunden wird, unterhalb von myStuff.js, und sie wurde als 1.2.6 angezeigt, wie ich erwartet hatte. Ich habe dann das Script-Tag entfernt und diese Zeile in myStuff.js eingefügt:

$.getScript("test.js");

und es kam immer noch als 1.2.6 zurück. Das war keine große Überraschung - laut Dokumentation von jQuery Skripte, die auf diese Weise eingebunden werden, werden im globalen Kontext ausgeführt. Ich habe dann versucht, dies stattdessen zu tun:

var testFn = $.proxy($.getScript, this);
testFn("test.js");

und es kam immer noch als 1.2.6 zurück. Nach einigem Herumprobieren habe ich herausgefunden, dass sich das Schlüsselwort "this" auf das Fenster bezieht, was vermutlich den globalen Kontext meint. Ich suche nach etwas, das ich anstelle von "this" einsetzen kann, um auf den Kontext der umschließenden Funktion zu verweisen, oder nach einer anderen Möglichkeit, den Code in der Datei von der umschließenden Funktion aus ausführen zu lassen. Ich habe bemerkt, dass es gut funktioniert, wenn ich den Code kopiere und einfüge, aber es ist ein großes Plugin, das an vielen Stellen verwendet wird, und ich würde es vorziehen, meine Datei nicht mit ihrem Code zu überladen. Mir sind die Ideen ausgegangen. Weiß jemand anders, wie man das macht?

3voto

Tgr Punkte 26333

Wenn Sie jQuery laden, wird lediglich ein Root jQuery-Objekt erstellt und die window.jQuery y window.$ um darauf hinzuweisen. Sie können also einfach das alte jQuery laden, die window.jQuery a window.jQuery126 laden Sie das neue jQuery, kopieren Sie window.jQuery a window.jQuery142 und ändern Sie dann window.jQuery y window.$ wenn Sie möchten, dass ein Plugin die andere Version verwendet.

Dies ist ein hässlicher und instabiler Hack, aber er sollte funktionieren, solange

  1. der gesamte Code, der für die nicht standardmäßige Version geschrieben wurde, ist mit (function($){...})($) (geeignete jQuery-Plugins sollten dies tun, und Sie können es leicht für Ihren eigenen Code sicherstellen)
  2. Skripte, die mit unterschiedlichen jQuery-Versionen verwendet werden, kommen sich nicht gegenseitig in die Quere (z. B. wenn ein Skript einen Event-Handler bindet und das andere versucht, die Bindung aufzuheben)

Eine andere, einfachere, aber weniger wartbare Lösung besteht darin, das Plugin so zu bearbeiten, dass es wie folgt aussieht (function($){...})(jQuery142) anstelle von (function($){...})(jQuery)

2voto

sirhc Punkte 6087

Versionen

Es gibt ein Skript, das speziell versucht, dieses Problem zu beheben: Versionen . Es ist allerdings schon ziemlich alt.

Es ist einfach ein nettes Hilfsmittel für den Wechsel der Versionen.

Ich habe dieses Skript zwar nicht selbst getestet, aber Sie können auf der Grundlage des GitHub-Repositorys für das Projekt etwas Ähnliches tun:

<!-- Old jQuery and it's plugins -->
<script type="text/javascript" src="../jquery/jquery-1.2.6.js"></script>
<script type="text/javascript" src="test-plugin-for-old.js"></script>

<!-- Include the Versions helper -->
<script type="text/javascript" src="versions.js"></script>

<!-- Include a new jQuery -->
<script type="text/javascript" src="../jquery/jquery.js"></script>
<script type="text/javascript">
Versions.add('jquery', 'latest', jQuery.noConflict(true));
Versions.add('jquery', 'default', jQuery);
</script>

<!-- Load a plugin into the new jQuery -->
<script type="text/javascript">jQuery = Versions.use('jquery', 'latest');</script>
<!-- Do whatever you need with the new jQuery -->
<script type="text/javascript" src="test-plugin-for-new.js"></script>
<!-- Finish up and use the old jQuery back -->
<script type="text/javascript">jQuery = Versions.use('jquery', 'default');</script>

Bedarfsgesteuertes Laden von JavaScript (Lazy Loading)

Damit ist das Thema erledigt, denn es gibt einige Möglichkeiten für das Laden von JavaScript auf Abruf aber ich glaube nicht, dass sie gut mit dem Laden von jQuery funktionieren werden, da jQuery das Vorhandensein der window Objekt.

Vielleicht möchten Sie auch etwas über das Laden von Skripten lesen. Es gibt mehr Details darüber in diese StackOverflow-Frage und die Artikel wies darauf hin .

RequireJS

In der Liste, RequireJS wird nicht erwähnt. Es ist ziemlich neu und man kann Dinge tun wie:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>
  <script type="text/javascript" src="pageStuff.js"></script>
</head>
<body>
Welcome to our page.
<div id="app">
    <script type="text/javascript" src="require.js"></script>
    <script type="text/javascript">
      require({context: "1.4.2"}, 
        ["http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"],
        function() {
          console.log($.fn.jquery); // returns 1.4.2
          // myStuff.js
        });
      require({context: "1.2.6"}, 
        ["http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"],
        function() {
          console.log($.fn.jquery); // returns 1.2.6
        });
    </script>
</div>
</body></html>

Ich kaufe immer die neuesten Sachen, haha, also empfehle ich das hier. Aufgrund der Art des Ladens von Jquery (es modifiziert window wie oben erwähnt), alle Verweise auf $ y jQuery außerhalb und jenseits des letzten require im obigen HTML-Codeblock bezieht sich auf jQuery 1.2.6.

0voto

Seb Punkte 24444

jQuery ist eigentlich eine Variable in der window Kontext. Wenn Sie also eine jQuery-Bibliothek laden, wird diese Variable in der window Kontext, wenn Sie ihn außerhalb einer Funktion laden.

I glauben Sie könnten so etwas tun, um das zu erreichen, was Sie wollen. Obwohl etwas restriktiv, sollte es theoretisch funktionieren:

<script type="text/javascript">
  // Get new jQuery code
  $.get( "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js", function (data, textStatus, XMLHttpRequest){
    if(data){
      // data should contain the file content. eval() it
      eval(data);

      // Use jQuery 1.4.2 from here, only inside this callback function.
    }
  }, "html" );
</script>

この でございます hässlich, aber es sollte reichen.

0voto

popeshoe Punkte 1
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" />
<script type="text/javascript">
    $new = $.noConflict();

    document.write("$new = " + $new.fn.jquery + "<br/>");
    document.write("$ = " + $.fn.jquery + "<br/>");

</script>

Ich habe gerade versucht, diese und es scheint zu funktionieren, $ Berichte, die alte Version zu sein, und Sie müssen nur sicherstellen, dass $new beim Aufrufen von jquery für das Zeug, das Sie mit 1.4.2 tun wollen, zu verwenden

0voto

Elias Zamaria Punkte 88450

Im Moment schließe ich mich der Lösung von Tgr an. Hier sind die Details, wie ich es implementiert:

Seite.html:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<script type="text/javascript" src="jquery-1.2.6.min.js>
<script type="text/javascript" src="pageStuff.js"></script>
</head>
<body>
Welcome to our page.
<div id="app">
    Here is our app.
    <script type="text/javascript">
        var oldJQuery = $;
    </script>
    <script type="text/javascript"
        src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
    <script type="text/javascript" src="myStuff.js"></script>
</div>
</body></html>

myStuff.js:

var jq142 = jQuery.noConflict(true);
(function($) {
    var jQuery = $;
    $(function() {
        //init app stuff
        includeScript("jCarousel.js", function() {
            //init carousel stuff
        });
    });
})(jq142);

function includeScript(URL, callback) {
    window.$ = window.jQuery = jq142;
    window.$.ajax({
        url: URL,
        dataType: "script",
        error: function() {
            window.$ = window.jQuery = oldJQuery;
        },
        success: function() {
            if (typeof callback != "undefined")
                callback();
            window.$ = window.jQuery = oldJQuery;
        },
        async: false
    });
}

Die Idee, eine weitere Variable (jq142) in den globalen Namensraum zu stellen, gefällt mir immer noch nicht, aber ich konnte mir keinen vernünftigen Ausweg vorstellen. Wenn mir etwas Besseres einfällt, werde ich es hier posten.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X