处理在加载jQuery之前依赖于jQuery的代码

我想遵循将所有JavaScript放在页面底部的一般准则,以加快加载时间,并在Web应用程序(Django)中处理与jQuery版本冲突的一些棘手问题。

但是,我经常会有一些代码,代码依赖于jQuery,但必须在页面上进一步提升(基本上代码不能移到底部)。

我想知道是否有一种简单的方法来编写代码,以便即使jQuery尚未定义,代码也可以在定义jQuery时运行。

我不得不说,以下似乎有点矫枉过正,但我​​不知道另一种方法:

function run_my_code($) { // jquery-dependent code here $("#foo").data('bar', true); } var t = null; function jquery_ready() { if (window.jQuery && window.jQuery.ui) { run_my_code(window.jQuery); } else { t = window.setTimeout(jquery_ready, 100); } } t = window.setTimeout(jquery_ready, 100); 

实际上,我可能需要在页面中不止一次使用代码,代码不知道其他代码,所以即使这可能也行不通,除非我将每个jquery_ready重命名为jquery_ready_ guid ,jquery_ready_ otherguid等等。

澄清

就这么清楚,我在页面的最底部 ,在之前将include包含到JavaScript( )中。 。 所以我不能用$

你的方式是我所知道的唯一方式,尽管我会确保范围更加严格:

 (function() { var runMyCode = function($) { // jquery-dependent code here $("#foo").data('bar', true); }; var timer = function() { if (window.jQuery && window.jQuery.ui) { runMyCode(window.jQuery); } else { window.setTimeout(timer, 100); } }; timer(); })(); 

更新

这是我拼凑在一起的一个延迟加载器:

 var Namespace = Namespace || { }; Namespace.Deferred = function () { var functions = []; var timer = function() { if (window.jQuery && window.jQuery.ui) { while (functions.length) { functions.shift()(window.jQuery); } } else { window.setTimeout(timer, 250); } }; timer(); return { execute: function(onJQueryReady) { if (window.jQuery && window.jQuery.ui) { onJQueryReady(window.jQuery); } else { functions.push(onJQueryReady); } } }; }(); 

那将是可用的如下:

 Namespace.Deferred.execute(runMyCode); 

我找到的最好方法是在函数中编写代码并在加载jquery后调用函数:

 function RunAfterjQ(){ // Codes that uses jQuery }   

更新:对于母版页,您可以定义一个数组以在主页面的头部推送函数:

 var afterJQ = []; 

然后在母版页的底部运行所有推入此数组的函数:

   

您需要使用依赖于jQuery的javascript并且在定义jQuery之前将其推入此数组:

 afterJQ.push( function() { // this code will execute after jQuery is loaded. }); 

这是一种编写注入代码的方法,只有在jQuery加载(无论是同步还是异步)之后才能运行。 deferAfterjQueryLoaded数组的结构基于@ Parris的答案 。

  

这样做是:

  1. deferAfterjQueryLoaded地定义deferAfterjQueryLoaded ,因此您不需要将其注入head
  2. window.$定义一个setter window.$ 。 当jQuery加载时,它做的最后一件事就是分配给全局$变量。 这允许您在发生这种情况时触发function。
  3. 在jQuery脚本完成后,计划延迟函数尽快运行( setTimeout(..., 0); )。
  4. 设定者是否自行删除。

为了完全清洁,您可以使用预定函数删除deferAfterjQueryLoaded

简单使用纯$(document).ready(); javascript版本的$(document).ready();

 document.addEventListener("DOMContentLoaded", function(event) { //you can use jQuery there }); 

怎么样:

    

这是有效的,因为这里的每个脚本都完全阻塞 这意味着创建deferAfterjQueryLoaded数组并首先创建并推送到该数组的所有函数。 然后jQuery完全加载。 然后迭代该数组并执行每个函数。 如果脚本在单独的文件中也是如此,这种方法也是如此。

如果您还想要激活DOMReady,可以在其中一个deferAfterjQueryLoaded函数中嵌入$(function() {}) ,如下所示:

 window.deferAfterjQueryLoaded.push(function() { $(function() { console.log('jquery loaded and the DOM is ready'); }); console.log('jquery loaded'); }); 

最终,你应该真正重构你的代码,所以一切都在底层,并有一个有利于该模型的系统。 更容易理解发生的一切并且性能更高(特别是如果你有单独的脚本)。

我有同样的问题,但有大量的文件,我使用headjs来管理加载,它只有2kb所以没有真正的问题,对我来说无论如何,放入标题。 你的代码变成了,

 head.ready(function(){ $... }); 

在页面底部,

 head.js('/jquery.min.js'); 

您应该能够在document ready事件上执行此操作。

 function jQueryGodot(code) { if (window.jQuery) { code(window.jQuery); } else { if (!window.$) { window.$ = { codes: [] }; window.watch('$', function(p, defered, jQuery) { jQuery.each(defered.codes, function(i, code) { code(jQuery); }); return jQuery; }); } window.$.codes.push(code); } } jQueryGodot(function($) { $('div').html('Will always work!'); }) 

关于JSFiddle的工作示例 。

传递给jQueryGodot函数的代码将始终执行,无论是在加载jQuery之前还是之后调用它。

该解决方案依赖于Object.watch,它在大多数浏览器中需要这个polyfill(缩小660字节): https : //gist.github.com/adriengibrat/b0ee333dc1b058a22b66

您可以在没有 setTimeout循环的情况下推迟所有调用,如jQuery(function(){…}): https : //jsfiddle.net/rL1f451q/3/

它将每个jQuery(…)调用收集到一个数组中,直到没有定义jQuery,然后第二个代码在jQuery可用时执行它们。

把它放在头部或身体的开头:

    

这是在jQuery脚本之后的身体的最后: