Załaduj jQuery z Javascriptem i użyj jQuery

85

Dołączam bibliotekę jQuery do domeny za pomocą:

 var script = document.createElement('script');
 script.src = 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js';
 script.type = 'text/javascript';
 document.getElementsByTagName('head')[0].appendChild(script);

Jednak kiedy biegam:

jQuery(document).ready(function(){...

Konsola zgłasza błąd:

Uncaught ReferenceError: jQuery is not defined

Jak dynamicznie ładować jQuery i używać go, gdy jest już w dom?

ThomasReggi
źródło
2
Czy jest jakiś powód, dla którego chcesz to zrobić w porównaniu z bardziej zoptymalizowanym sposobem?
Code Maverick
Niektóre odpowiedzi na to pytanie mogą ci pomóc - stackoverflow.com/questions/7474354/ ...
mrtsherman
@Scott Yes. Mam aplikację, w której podczas instalacji ładuje zarówno jquery, jak i skrypt. Muszę załadować jquery w skrypcie, aby jquery nie zepsuł motywów użytkowników. Muszę warunkowo załadować JavaScript na określoną stronę internetową w ramach ich motywu. Proszę, zaufaj mi w tej sprawie.
ThomasReggi,
Dlaczego jQuery miałby łamać motywy użytkowników? Jeśli ładowanie jQuery (które nie ma wpływu na css) może zepsuć motywy, robisz coś bardzo złego.
Anders Tornblad
Słuszna uwaga, ale co, jeśli używają starszej wersji jQuery lub innej biblioteki?
ThomasReggi,

Odpowiedzi:

140

Jest tutaj działający JSFiddle z małym przykładem, który pokazuje dokładnie, czego szukasz (chyba że źle zrozumiałem twoją prośbę) : http://jsfiddle.net/9N7Z2/188/

Istnieje kilka problemów z tą metodą dynamicznego ładowania javascript. Jeśli chodzi o bardzo podstawowe frameworki, takie jak jQuery, prawdopodobnie chcesz je ładować statycznie, ponieważ w przeciwnym razie musiałbyś napisać cały framework ładujący JavaScript ...

Możesz użyć niektórych istniejących programów ładujących JavaScript lub napisać własne, obserwując, window.jQueryaby uzyskać definicję.

// Immediately-invoked function expression
(function() {
    // Load the script
    var script = document.createElement("SCRIPT");
    script.src = 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js';
    script.type = 'text/javascript';
    script.onload = function() {
        var $ = window.jQuery;
        // Use $ here...
    };
    document.getElementsByTagName("head")[0].appendChild(script);
})();

Pamiętaj tylko, że jeśli potrzebujesz obsługi naprawdę starych przeglądarek, takich jak IE8, programy loadobsługi zdarzeń nie działają. W takim przypadku musisz sondować, czy istnieje window.jQueryużycie funkcji powtórzone window.setTimeout. Istnieje działający JSFiddle z tą metodą tutaj: http://jsfiddle.net/9N7Z2/3/

Jest wielu ludzi, którzy już zrobili to, co trzeba. Sprawdź niektóre z istniejących frameworków JavaScript Loader, takich jak:

Anders Tornblad
źródło
To rozwiązanie działa, z wyjątkiem WordPressa. Jakikolwiek sposób można to zmodyfikować, aby załadować jQuery do innego obiektu?
Kraang Prime
@SanuelJackson W Wordpress, powinieneś użyć wp_enqueue_script()funkcji, aby poprawnie dołączyć jQuery. Dokumentacja: codex.wordpress.org/Function_Reference/wp_enqueue_script Więcej informacji tutaj: digwp.com/2009/06/includes-jquery-in-wordpress-the-right-way lub tutaj: digwp.com/2011/09/using- zamiast jquery-in-wordpress
Anders Tornblad
Tak, mówiłem, że powyższy kod nie działa na Wordpress, ponieważ ładuje również jQuery asynchronicznie. Nawet jeśli ten skrypt jest ładowany na samym dole strony (tuż przed zamknięciem html), jQuery nie jest w pełni „zainicjowany”, a zatem nie widzi wczytanego jQuery i kontynuuje ładowanie i wykonywanie wywołania zwrotnego. Po załadowaniu psuje inne rzeczy, które zostały załadowane asynchronicznie, które zależały od załadowania jQuery w inny sposób (np. $, JQuery itp.) Lub zależały od innej wersji jQuery.
Kraang Prime
W innych przypadkach jest świetny. Właśnie zanotowałem jedyny rażący problem z tym. Gdyby w jakiś sposób dało się to dostroić, ale nie sądzę, że jest to możliwe, ponieważ zależy to od wykrycia jQuery, które oczywiście nie jest załadowane, a zatem może postępować tylko z logiką - jeśli nie ma jquery ... to ..
Kraang Prime
1
Nie musisz wykonywać odpytywania, możesz użyć tylko jednej linii, aby poczekać, aż jquery załaduje się, używając zdarzenia .onload, takiego jak stackoverflow.com/a/42013269/3577695
aljgom
7

Istnieje inny sposób dynamicznego ładowania jQuery ( źródło ). Możesz również użyć

document.write('<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"><\/script>');

Jest to uważane za złą praktykę document.write, ale ze względu na zakończenie dobrze o tym wspomnieć.

Zobacz Dlaczego document.write jest uważana za „złą praktykę”? z powodów. Pro jest to, że document.writenie blokować strony z ładowania innych assests, więc nie ma potrzeby, aby utworzyć funkcję zwrotną.

Jacob van Lingen
źródło
1
Przeczytałem dokument, do którego linkowałeś, i dla mojego przypadku ładowania starszej biblioteki jQuery dla IE8, użycie document.write wydaje się być w porządku. Jak na razie działa dobrze.
Alan
To najłatwiejszy i najprostszy sposób na zrobienie tego. Czy wystąpiłby problem z zrobieniem tego na początku dość dużego skryptu, który jest oddzielnym plikiem JS? Jest zbyt dobrze, żeby zrezygnować.
Agustín Lado
6

Strona internetowa Encosia poleca:

<script type="text/javascript" 
        src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
  // You may specify partial version numbers, such as "1" or "1.3",
  //  with the same result. Doing so will automatically load the 
  //  latest version matching that partial revision pattern 
  //  (e.g. 1.3 would load 1.3.2 today and 1 would load 1.7.2).
  google.load("jquery", "1.7.2");

  google.setOnLoadCallback(function() {
    // Place init code here instead of $(document).ready()
  });
</script>

Ale nawet on przyznaje, że nie ma to porównania z robieniem następujących rzeczy, jeśli chodzi o optymalną wydajność:

    <script src="//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.2.min.js" type="text/javascript"></script>
    <script type="text/javascript"> window.jQuery || document.write('<script src="js/libs/jquery-1.7.2.min.js">\x3C/script>')</script>
    <script type="text/javascript" src="scripts.js"></scripts>
</body>
</html>
Code Maverick
źródło
Mogę załadować tylko jeden javascript. Oznaczałoby to, że musiałbym dynamicznie ładować google jsapi z tego ładowania jquery? Wydaje się zbędne w moim przypadku użycia.
ThomasReggi,
1
To właśnie robi moduł ładujący jQuery. Odwołujesz się do modułu ładującego, a moduł ładujący wstrzykuje jQuery do dokumentu za Ciebie.
Code Maverick
3

Musisz uruchomić swój kod PO zakończeniu ładowania jQuery

var script = document.createElement('script'); 
document.head.appendChild(script);    
script.type = 'text/javascript';
script.src = "//ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js";
script.onload = function(){
    // your jQuery code here
} 

lub jeśli uruchamiasz go w funkcji asynchronicznej, której możesz użyć awaitw powyższym kodzie

var script = document.createElement('script'); 
document.head.appendChild(script);    
script.type = 'text/javascript';
script.src = "//ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js";
await script.onload
// your jQuery code here

Jeśli chcesz najpierw sprawdzić, czy jQuery już istnieje na stronie, spróbuj tego

aljgom
źródło
0

Powodem, dla którego otrzymujesz ten błąd, jest to, że JavaScript nie czeka na załadowanie skryptu, więc po uruchomieniu

jQuery(document).ready(function(){...

nie ma gwarancji, że skrypt jest gotowy (i nigdy nie będzie).

Nie jest to najbardziej eleganckie rozwiązanie, ale wykonalne. Zasadniczo możesz sprawdzać co 1 sekundę, czy reklama obiektu jQuery uruchamia funkcję po załadowaniu jej kodu. Dodałbym limit czasu (powiedzmy clearTimeout po jego uruchomieniu 20 razy), jak również, aby zatrzymać czekanie przed występowaniem w nieskończoność.

var jQueryIsReady = function(){
    //Your JQuery code here
}

var checkJquery = function(){
    if(typeof jQuery === "undefined"){
        return false;
    }else{
        clearTimeout(interval);
        jQueryIsReady();
    }
}
var interval = setInterval(checkJquery,1000);
marteljn
źródło
0

Korzystając z require.js , możesz zrobić to samo w bezpieczniejszy sposób. Możesz po prostu zdefiniować swoją zależność od jquery, a następnie wykonać kod, który chcesz, używając zależności podczas ładowania, bez zanieczyszczania przestrzeni nazw:

Generalnie polecam tę bibliotekę do zarządzania wszystkimi zależnościami od Javascript. Jest prosta i pozwala na efektywną optymalizację ładowania zasobów. Istnieją jednak pewne środki ostrożności, których możesz potrzebować podczas używania go z JQuery. Mój ulubiony sposób radzenia sobie z nimi jest wyjaśniony w tym repozytorium github i odzwierciedlony w poniższym przykładzie kodu:

<title>jQuery+RequireJS Sample Page</title>
   <script src="scripts/require.js"></script>
   <script>
   require({
       baseUrl: 'scripts',
       paths: {
           jquery: 'https://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min'
       },
       priority: ['jquery']
    }, ['main']);
    </script>
txominpelu
źródło
0

HTML:

<html>
  <head>

  </head>
  <body>

    <div id='status'>jQuery is not loaded yet.</div>
    <input type='button' value='Click here to load it.' onclick='load()' />

  </body>
</html>   

Scenariusz:

   <script>

        load = function() {
          load.getScript("jquery-1.7.2.js");
          load.tryReady(0); // We will write this function later. It's responsible for waiting until jQuery loads before using it.
        }

        // dynamically load any javascript file.
        load.getScript = function(filename) {
          var script = document.createElement('script')
          script.setAttribute("type","text/javascript")
          script.setAttribute("src", filename)
          if (typeof script!="undefined")
          document.getElementsByTagName("head")[0].appendChild(script)
        }

        </script>
koder
źródło
Trudną częścią jest uruchomienie skryptu po załadowaniu skryptu ... I dlaczego skrypt miałby być kiedykolwiek niezdefiniowany! ??
Anders Tornblad