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

Jor*_*ter 32 javascript 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);
Run Code Online (Sandbox Code Playgroud)

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

澄清

就是这样很明显,我将include(包括JavaScript <script type="text/javascript" src="jquery.min.js" />)放在页面的最底部,就在之前</body>.所以我不能用$.

bod*_*sog 19

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

document.addEventListener("DOMContentLoaded", function(event) { 
    //you can use jQuery there
});
Run Code Online (Sandbox Code Playgroud)


Ric*_*lly 17

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

(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();
})();
Run Code Online (Sandbox Code Playgroud)

更新

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

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);
        }
    }
  };
}();
Run Code Online (Sandbox Code Playgroud)

哪个可以这样使用:

Namespace.Deferred.execute(runMyCode);
Run Code Online (Sandbox Code Playgroud)


Ash*_*ani 17

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

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

<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
<script type="text/javascript">
    RunAfterjQ();
</script>
Run Code Online (Sandbox Code Playgroud)

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

var afterJQ = [];
Run Code Online (Sandbox Code Playgroud)

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

<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
<script type="text/javascript">
    for(var i = 0; i < afterJQ.length; i++) afterJQ[i]();
</script>
Run Code Online (Sandbox Code Playgroud)

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

afterJQ.push( function() { 
    // this code will execute after jQuery is loaded.
 });
Run Code Online (Sandbox Code Playgroud)

  • 很棒的答案!最简单,最快捷,工作完美! (3认同)

rad*_*aph 10

这是一种编写注入代码的方法,只有在jQuery加载(无论是同步还是异步)之后才能运行.

<script>
if ( ! window.deferAfterjQueryLoaded ) {
    window.deferAfterjQueryLoaded = [];
    Object.defineProperty(window, "$", {
        set: function(value) {
            window.setTimeout(function() {
                $.each(window.deferAfterjQueryLoaded, function(index, fn) {
                    fn();
                });
            }, 0);
            Object.defineProperty(window, "$", { value: value });
        },

        configurable: true
    });
}

window.deferAfterjQueryLoaded.push(function() {
    //... some code that needs to be run
});
</script>
Run Code Online (Sandbox Code Playgroud)

这样做是:

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

为了完全清洁,您也可以删除预定的功能deferAfterjQueryLoaded.


Par*_*ris 7

怎么样:

<script>
    window.deferAfterjQueryLoaded = [];
    window.deferAfterjQueryLoaded.push(function() {
        //... some code that needs to be run
    });

    // ... further down in the page

    window.deferAfterjQueryLoaded.push(function() {
        //... some other code to run
    });
</script>

<script src="jquery.js" />
<script>
    $.each(window.deferAfterjQueryLoaded, function(index, fn) {
        fn();
    });
</script>
Run Code Online (Sandbox Code Playgroud)

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

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

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

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