如何使脚本执行等到jquery加载
我有一个问题,页面加载速度如此之快,jquery还没有完成加载之前被后续脚本调用。 有没有办法来检查jQuery的存在,如果它不存在,等一会,然后再试一次?
回答下面的答案/评论,我张贴了一些标记。
情况… asp.net masterpage和childpage。
在masterpage中,我有一个jQuery的参考。 然后在内容页面中,我引用了特定于页面的脚本。 当页面特定的脚本被加载时,它抱怨“$未定义”。
我在标记中的几个点上发出警报,以查看事情发生的顺序,并确认它按以下顺序触发:
- 主页面标题。
- 子页面内容块1(位于masterpage的头部内,但在调用masterpage脚本之后)。
- 子页面内容块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(); }); });
编辑
你可以尝试正确的types为您的脚本标签? 我看到你使用text/Scripts
,这不是正确的mimetype的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代码的加载器。
取决于你的项目,这可能会有点矫枉过正
晚了,和Briguy37的问题类似,但为了将来的参考,我使用下面的方法,并传递我要推迟的function,直到加载jQuery:
function defer(method) { if (window.jQuery) { method(); } else { setTimeout(function() { defer(method) }, 50); } }
它会recursion调用延迟方法每50ms,直到window.jQuery
存在,在这个时候它退出并调用method()
一个匿名函数的例子:
defer(function () { alert("jQuery is now loaded"); });
你可以使用defer属性在真正的结尾加载脚本。
<script type='text/javascript' src='myscript.js' defer='defer'></script>
但通常以正确的顺序加载您的脚本应该做的伎俩,所以一定要把jQuery包含在自己的脚本之前
如果你的代码是在页面中,而不是在一个单独的js文件中,所以你必须在文档准备好之后才能执行你的脚本,并且像这样封装你的代码也应该工作:
$(function(){ //here goes your code });
还有另外一个办法,虽然Darbio的推迟方法更灵活。
(function() { var nTimer = setInterval(function() { if (window.jQuery) { // Do something with jQuery clearInterval(nTimer); } }, 100); })();
你可以尝试onload事件。 当所有的脚本被加载时引发:
window.onload = function () { //jquery ready for use here }
但请记住,您可以覆盖window.onload使用的其他脚本。
这是一个常见的问题,想象你使用一个很酷的PHP模板引擎,所以你有你的基本布局:
HEADER BODY ==> dynamic CONTENT/PAGE FOOTER
当然,你也可以在页面底部加载Javascript,所以你的dynamic内容不知道谁是jQuery(或$)。
另外,你也可以在某处阅读小的Javascript,所以假设你需要在页面中使用jQuery,baboom,$没有定义(.. yet ^^)。
我喜欢Facebook提供的解决scheme
window.fbAsyncInit = function() { alert('FB is ready !'); }
所以作为一个懒惰的程序员(我应该说一个好的程序员^^),你可以使用一个等价的(在你的页面中):
window.jqReady = function() {}
在jQuery包含之后,在布局的底部添加
if (window.hasOwnProperty('jqReady')) $(function() {window.jqReady();});
使用:
$(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();
而不是“等待”(通常使用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 } }); })();
我不认为这是你的问题。 脚本加载是默认同步的,所以除非你使用defer
属性或者通过另一个AJAX请求加载jQuery本身,否则你的问题可能更像404.你能显示你的标记,并且让我们知道你是否看到任何可疑的东西在萤火虫或networking督察?
检查这个:
https://jsfiddle.net/neohunter/ey2pqt5z/
它会创build一个假的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);
最简单和最安全的方法是使用这样的东西:
var waitForJQuery = setInterval(function () { if (typeof $ != 'undefined') { // place your code here. clearInterval(waitForJQuery); } }, 10);
我不喜欢间隔的东西。 当我想推迟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="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="jquery-3.2.1.min.js" type="text/javascript"></script> <script>for(var f in def){def[f]();}</script>
而在asynchronous的情况下,你可以在jQuery的onload上执行推送的function。
<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]();}});