簡體   English   中英

如何使腳本執行等到加載jquery

[英]How to make script execution wait until jquery is loaded

我遇到了頁面加載速度如此之快的問題,以至於jquery在后續腳本調用之前尚未完成加載。 有沒有一種方法可以檢查是否存在jquery,如果不存在,請稍等片刻,然后重試?


針對以下答案/評論,我將發布一些標記。

情況... asp.net母版頁和子頁。

在母版頁中,我引用了jquery。 然后,在內容頁面中,我引用了特定於頁面的腳本。 當頁面特定腳本被加載時,它抱怨“ $未定義”。

我在標記中的幾個點上放置了警報,以查看事物觸發的順序,並確認它按以下順序觸發:

  1. 母版頁眉。
  2. 子頁面內容塊1(位於母版頁頭內部,但在調用母版頁腳本之后)。
  3. 子頁面內容塊2。

這是母版頁頂部的標記:

<%@ 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>

然后,在母版頁的正文中,還有一個ContentPlaceHolder:

 <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
                </asp:ContentPlaceHolder>

在子頁面中,如下所示:

<%@ 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>

這是“ ../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();
    });

});

晚會晚了,類似於Briguy37的問題,但是為了以后參考,我使用以下方法並將要推遲到加載jQuery的函數傳遞給我:

function defer(method) {
    if (window.jQuery) {
        method();
    } else {
        setTimeout(function() { defer(method) }, 50);
    }
}

它將每隔50ms遞歸地調用defer方法,直到window.jQuery存在,然后退出並調用method()

具有匿名功能的示例:

defer(function () {
    alert("jQuery is now loaded");
});

您可以使用defer屬性在實際末尾加載腳本。

<script type='text/javascript' src='myscript.js' defer='defer'></script>

但通常以正確的順序加載腳本應該可以解決問題,因此請確保將jquery include放在您自己的腳本之前

如果您的代碼在頁面中,而不是在單獨的js文件中,那么您只需要在文檔准備好並封裝代碼后執行腳本即可,如下所示:

$(function(){
//here goes your code
});

盡管達比奧(Darbio)的延期方法更為靈活,但還有另一種方法。

(function() {
  var nTimer = setInterval(function() {
    if (window.jQuery) {
      // Do something with jQuery
      clearInterval(nTimer);
    }
  }, 100);
})();

最簡單,最安全的方法是使用以下代碼:

var waitForJQuery = setInterval(function () {
    if (typeof $ != 'undefined') {

        // place your code here.

        clearInterval(waitForJQuery);
    }
}, 10);

編輯

您能為腳本標簽嘗試正確的類型嗎? 我看到您使用text/Scripts ,這不是JavaScript的正確模仿類型。

用這個:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> 
<script type="text/javascript" src="../Scripts/jquery.dropdownPlain.js"></script>
<script type="text/javascript" src="../Scripts/facebox.js"></script>

結束編輯

或者您可以查看require.js ,它是您的JavaScript代碼的加載程序。

根據您的項目,這可能有點過大

您可以嘗試onload事件。 加載所有腳本后引發:

window.onload = function () {
   //jquery ready for use here
}

但請記住,您可以覆蓋使用window.onload的其他腳本。

我發現建議的解決方案僅在考慮異步代碼時才有效。 這是在兩種情況下都可以使用的版本:

document.addEventListener('DOMContentLoaded', function load() {
    if (!window.jQuery) return setTimeout(load, 50);
    //your synchronous or asynchronous jQuery-related code
}, false);

這是一個常見的問題,想象一下您使用了一個很酷的PHP模板引擎,因此您有了基本的布局:

HEADER
BODY ==> dynamic CONTENT/PAGE
FOOTER

當然,您可能會在頁面底部閱讀Java腳本,因此,動態內容不知道誰是jQuery(或$)。

另外,您在某處閱讀了內聯小型Java腳本是很好的,因此,假設您需要在頁面baboom中使用jQuery,未定義$(.. yet ^^)。

我喜歡Facebook提供的解決方案

window.fbAsyncInit = function() { alert('FB is ready !'); }

因此,作為一個懶惰的程序員(我應該說一個好的程序員^^),您可以使用等效項(在您的頁面內):

window.jqReady = function() {}

並在jQuery包含之后在布局的底部添加

if (window.hasOwnProperty('jqReady')) $(function() {window.jqReady();});

除了“ wait”(通常使用setTimeout完成),您還可以在窗口本身中使用jQuery對象的定義作為執行依賴於它的代碼的鈎子。 這可以通過使用Object.defineProperty定義的屬性定義來Object.defineProperty

(function(){
  var _jQuery;
  Object.defineProperty(window, 'jQuery', {
    get: function() { return _jQuery; },
    set: function($) {
      _jQuery = $;

      // put code or call to function that uses jQuery here

    }
  });
})();

采用:

$(document).ready(function() {
    // put all your jQuery goodness in here.
});

查看此以獲取更多信息: http : //www.learningjquery.com/2006/09/introducing-document-ready

注意:只要您的JQuery庫的腳本導入在此調用之上,此方法就應該起作用。

更新:

如果由於某種原因您的代碼未同步加載( 我從未遇到過,但顯然可能 不會發生 以下注釋 ),則可以像下面這樣編碼。

function yourFunctionToRun(){
    //Your JQuery goodness here
}

function runYourFunctionWhenJQueryIsLoaded() {
    if (window.$){
        //possibly some other JQuery checks to make sure that everything is loaded here

        yourFunctionToRun();
    } else {
        setTimeout(runYourFunctionWhenJQueryIsLoaded, 50);
    }
}

runYourFunctionWhenJQueryIsLoaded();

我不認為這是你的問題。 默認情況下,腳本加載是同步的,因此,除非您使用defer屬性或通過另一個AJAX請求加載jQuery本身,否則問題可能更像是404。您可以顯示您的標記,如果發現任何可疑內容,請告訴我們在螢火蟲或網頁檢查器中?

檢查一下:

https://jsfiddle.net/neohunter/ey2pqt5z/

它將創建一個偽造的jQuery對象,該對象允許您使用jquery的onload方法,並且將在加載jquery后立即執行它們。

這不是完美的。

 // This have to be on <HEAD> preferibly inline var delayed_jquery = []; jQuery = function() { if (typeof arguments[0] == "function") { jQuery(document).ready(arguments[0]); } else { return { ready: function(fn) { console.log("registering function"); delayed_jquery.push(fn); } } } }; $ = jQuery; var waitForLoad = function() { if (typeof jQuery.fn != "undefined") { console.log("jquery loaded!!!"); for (k in delayed_jquery) { delayed_jquery[k](); } } else { console.log("jquery not loaded.."); window.setTimeout(waitForLoad, 500); } }; window.setTimeout(waitForLoad, 500); // end // now lets use jQuery (the fake version) jQuery(document).ready(function() { alert('Jquery now exists!'); }); jQuery(function() { alert('Jquery now exists, this is using an alternative call'); }) // And lets load the real jquery after 3 seconds.. window.setTimeout(function() { var newscript = document.createElement('script'); newscript.type = 'text/javascript'; newscript.async = true; newscript.src = 'https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js'; (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(newscript); }, 3000); 

我不喜歡間隔事物。 當我想推遲jquery或其他實際操作時,通常會發生如下情況。

從...開始:

<html>
 <head>
  <script>var $d=[];var $=(n)=>{$d.push(n)}</script>
 </head>

然后:

 <body>
  <div id="thediv"></div>

  <script>
    $(function(){
       $('#thediv').html('thecode');
    });
  </script>

  <script src="http://code.jquery.com/jquery-3.2.1.min.js" type="text/javascript"></script>

然后最后:

  <script>for(var f in $d){$d[f]();}</script>
 </body>
<html>

或令人難以置信的版本:

<script>var def=[];function defer(n){def.push(n)}</script>
<script>
defer(function(){
   $('#thediv').html('thecode');
});
</script>
<script src="http://code.jquery.com/jquery-3.2.1.min.js" type="text/javascript"></script>
<script>for(var f in def){def[f]();}</script>

並且在異步的情況下,您可以在jQuery onload上執行推送的功能。

<script async onload="for(var f in def){def[f]();}" 
src="jquery.min.js" type="text/javascript"></script>

或者:

function loadscript(src, callback){
  var script = document.createElement('script');
  script.src = src
  script.async = true;
  script.onload = callback;
  document.body.appendChild(script);
};
loadscript("jquery.min", function(){for(var f in def){def[f]();}});

關於此處使用setTimeoutsetInterval加載的方法的setInterval 在這些情況下,有可能當您再次執行檢查時,DOM將已經加載,並且瀏覽器的DOMContentLoaded事件將被觸發,因此您無法使用這些方法可靠地檢測到該事件。 我發現的是,jQuery的ready仍然有效,不過,這樣你就可以嵌入你平常

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

在您的setTimeoutsetInterval ,一切都應該正常工作。

讓我們從Dario擴展defer()使其更可重用。

function defer(toWaitFor, method) {
    if (window[toWaitFor]) {
        method();
    } else {
        setTimeout(function () { defer(toWaitFor, method) }, 50);
    }
}

然后運行:

function waitFor() {
    defer('jQuery', () => {console.log('jq done')});
    defer('utag', () => {console.log('utag done')});
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM