Mam problem, gdy strona ładuje się tak szybko, że jquery nie zakończyło ładowania przed wywołaniem jej przez kolejny skrypt. Czy jest sposób, aby sprawdzić istnienie jquery, a jeśli nie istnieje, poczekaj chwilę, a następnie spróbuj ponownie?
W odpowiedzi na poniższe odpowiedzi / komentarze zamieszczam część znaczników.
Sytuacja ... asp.net masterpage i childpage.
Na masterpage mam odniesienie do jquery. Następnie na stronie treści mam odniesienie do skryptu specyficznego dla strony. Kiedy ładowany jest skrypt specyficzny dla strony, narzeka, że „$ jest niezdefiniowane”.
Umieściłem alerty w kilku punktach znaczników, aby zobaczyć kolejność, w jakiej zostały uruchomione, i potwierdziłem, że odpala w tej kolejności:
- Nagłówek strony wzorcowej.
- Blok zawartości strony podrzędnej 1 (znajduje się w nagłówku strony głównej, ale po wywołaniu skryptów strony głównej).
- Blok zawartości strony podrzędnej 2.
Oto znaczniki u góry strony głównej:
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="SiteMaster" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Reporting Portal</title>
<link href="~/Styles/site.css" rel="stylesheet" type="text/css" />
<link href="~/Styles/red/red.css" rel="stylesheet" type="text/css" />
<script type="text/Scripts" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/Scripts" language="javascript" src="../Scripts/jquery.dropdownPlain.js"></script>
<script type="text/Scripts" language="javascript" src="../Scripts/facebox.js"></script>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
</head>
Następnie w treści strony głównej znajduje się dodatkowy element ContentPlaceHolder:
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
Na stronie podrzędnej wygląda to tak:
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Dashboard.aspx.cs" Inherits="Data.Dashboard" %>
<%@ Register src="../userControls/ucDropdownMenu.ascx" tagname="ucDropdownMenu" tagprefix="uc1" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
<link rel="stylesheet" type="text/css" href="../Styles/paserMap.css" />
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
***CONTENT HERE***
<script src="../Scripts/Dashboard.js" type="text/javascript"></script>
</asp:Content>
Oto zawartość pliku „../Script/Dashboard.js”:
$(document).ready(function () {
$('.tgl:first').show(); // Show the first div
//Description: East panel parent tab navigation
$('.tabNav label').click(function () {
$('.tabNav li').removeClass('active')
$(this).parent().addClass('active');
var index = $(this).parent('li').index();
var divToggle = $('.ui-layout-content').children('div.tgl');
//hide all subToggle divs
divToggle.hide();
divToggle.eq(index).show();
});
});
źródło
$(document).ready(function(){...});
?<script src="...">
tagami, to nie może się zdarzyć. Czy używasz czegoś takiego jak RequireJS lub LABjs?$(document).ready()
lub$(window).load()
? Czy możemy zobaczyć przykład?type="text/Scripts"
siętype="text/javascript"
, lub pozbyć się go wszyscy razem nie jest już potrzebne, a także pozbyć sięlanguage="javascript
. Równie dobrze mógłbym zacząć próbować różnych rzeczy.Odpowiedzi:
edytować
Czy możesz wypróbować poprawny typ tagów skryptu? Widzę, że używasz
text/Scripts
, co nie jest właściwym typem MIME dla javascript.Użyj tego:
koniec edycji
lub możesz rzucić okiem na require.js, który jest programem ładującym twój kod javascript.
w zależności od projektu może to być jednak trochę przesada
źródło
Spóźniony na imprezę i podobny do pytania Briguy37, ale dla przyszłego odniesienia używam następującej metody i przekazuję funkcje, które chcę odroczyć, aż do załadowania jQuery:
Będzie rekurencyjnie wywoływać metodę odroczenia co 50 ms, aż będzie
window.jQuery
istniała, kiedy kończy działanie i wywołujemethod()
Przykład z funkcją anonimową:
źródło
script
tagdefer
ładujący jQuery miał atrybut, powodowałby problem, ładując się dopiero później, pomimo zdefiniowanej w kodzie kolejności skryptów.możesz użyć atrybutu defer, aby załadować skrypt na samym końcu.
ale normalnie ładowanie skryptu we właściwej kolejności powinno załatwić sprawę, więc pamiętaj, aby umieścić włączenie jquery przed własnym skryptem
Jeśli twój kod znajduje się na stronie, a nie w oddzielnym pliku js, musisz wykonać skrypt dopiero po przygotowaniu dokumentu, a hermetyzacja kodu również powinna działać:
źródło
Jeszcze inny sposób, aby to zrobić, chociaż metoda odroczenia Darbio jest bardziej elastyczna.
źródło
najłatwiej i najbezpieczniej jest użyć czegoś takiego:
źródło
Możesz spróbować zdarzenia onload. Został podniesiony, gdy wszystkie skrypty zostały załadowane:
Pamiętaj jednak, że możesz przesłonić inne skrypty, w których window.onload używa.
źródło
Odkryłem, że sugerowane rozwiązanie działa tylko z myślą o kodzie asynchronicznym. Oto wersja, która będzie działać w obu przypadkach:
źródło
load
funkcję, ale potem też ją ponownie wykorzystujęsetTimeout
.To częsty problem, wyobraź sobie, że używasz fajnego silnika do tworzenia szablonów PHP, więc masz swój podstawowy układ:
I oczywiście, gdzieś czytasz, lepiej załadować JavaScript na dole strony, aby Twoja dynamiczna zawartość nie wiedziała, kto to jest jQuery (lub $).
Czytałeś też gdzieś, że dobrze jest wbudować mały Javascript, więc wyobraź sobie, że potrzebujesz jQuery na stronie, baboom, $ nie jest zdefiniowane (.. jeszcze ^^).
Uwielbiam rozwiązanie oferowane przez Facebooka
Więc jako leniwy programista (powinienem powiedzieć dobry programista ^^) możesz użyć odpowiednika (na swojej stronie):
I dodaj u dołu swojego układu, po dołączeniu jQuery
źródło
Zamiast „czekać” (co jest zwykle wykonywane za pomocą
setTimeout
), możesz również użyć zdefiniowania obiektu jQuery w samym oknie jako punktu zaczepienia do wykonania kodu, który na nim opiera się. Można to osiągnąć poprzez definicję właściwości, zdefiniowaną za pomocąObject.defineProperty
.źródło
window.jQuery
wartość, definiującjQuery
zmienną w zakresie globalnym (tjwindow
.). Spowoduje to wyzwolenie funkcji ustawiającej właściwości w obiekcie okna zdefiniowanym w kodzie.</body>
zamiast przed</head>
Posługiwać się:
Sprawdź to, aby uzyskać więcej informacji: http://www.learningjquery.com/2006/09/introducing-document-ready
Uwaga: Powinno to działać, o ile import skryptu dla biblioteki JQuery jest powyżej tego wywołania.
Aktualizacja:
Jeśli z jakiegoś powodu twój kod nie ładuje się synchronicznie (co
nigdy nie spotkałem, ale najwyraźniej jest to możliwe z poniższego komentarzanie powinno się zdarzyć), możesz zakodować go w następujący sposób.źródło
Nie przepadam za rzeczami z przerwami. Kiedy chcę odroczyć jquery, a właściwie cokolwiek innego, zwykle wygląda to tak.
Zacząć od:
Następnie:
Wreszcie:
Lub mniej zadziwiająca wersja:
A w przypadku async możesz wykonywać wypychane funkcje na jquery onload.
Alternatywnie:
źródło
Rozwińmy
defer()
od Dario, aby było bardziej wielokrotnego użytku.Który jest następnie uruchamiany:
źródło
Nie sądzę, że to twój problem. Ładowanie skryptu jest domyślnie synchroniczne, więc jeśli nie używasz
defer
atrybutu lub nie ładujesz samego jQuery za pośrednictwem innego żądania AJAX, Twój problem jest prawdopodobnie czymś w rodzaju błędu 404. Czy możesz pokazać swoje znaczniki i daj nam znać, jeśli zobaczysz coś podejrzanego firebug czy inspektor sieci?źródło
Sprawdź to:
https://jsfiddle.net/neohunter/ey2pqt5z/
Stworzy on fałszywy obiekt jQuery, który pozwoli ci użyć metod onload jquery, i zostaną one wykonane zaraz po załadowaniu jquery.
To nie jest idealne.
źródło
Styczna uwaga na temat podejść tutaj, które używają obciążenia
setTimeout
lubsetInterval
. W takich przypadkach możliwe jest, że po ponownym uruchomieniu sprawdzenia DOM zostanie już załadowany, aDOMContentLoaded
zdarzenie przeglądarki zostanie uruchomione , więc nie można wiarygodnie wykryć tego zdarzenia przy użyciu tych podejść. Odkryłem jednak, że jQueryready
nadal działa, więc możesz osadzić swój zwykły plikjQuery(document).ready(function ($) { ... }
wewnątrz twojego
setTimeout
lubsetInterval
i wszystko powinno działać normalnie.źródło