条件加载jQuery

时间:2013-07-04 03:06:39

标签: javascript jquery

我正在使用纯JavaScript进行测试,如果浏览器似乎支持HTML5,如果是这样,我想加载jQuery然后处理页面的其余部分。如果没有,将发生一些重定向。

  <script type="text/javascript">
    var canvas = document.createElement('canvas');
    if (canvas && canvas.getContext && canvas.getContext('2d')) {
      var s = document.getElementsByTagName('script')[0];
      var jq = document.createElement('script');
      jq.type = 'text/javascript';
      jq.src = 'js/jquery.js';
      s.parentNode.insertBefore(jq, s);
    }
    else {
      // ... redirection ...
    }
  </script>
  <script type="text/javascript">
    $(function () {
      //...
    }
  </script>

但上面的代码工作不正常,因为我收到了错误

  Uncaught ReferenceError: $ is not defined

这清楚地表明jQuery库尚未加载。

为什么呢?在上面的代码中加载条件脚本有什么问题?

4 个答案:

答案 0 :(得分:4)

这是使用document.write()可能有意义的情况。您需要将此代码放在<body>而不是<head>

  <script type="text/javascript">
    var canvas = document.createElement('canvas');
    if (canvas && canvas.getContext && canvas.getContext('2d')) {
      document.write( '<script src="js/jquery.js"><\/script>' );
    }
    else {
      // ... redirection ...
    }
  </script>
  <script type="text/javascript">
    $(function () {
      //...
    }
  </script>

或者,您可以使用普通的<script>标记来加载jQuery,但在条件重定向之后将其设置为

  <script>
    var canvas = document.createElement('canvas');
    if( !( canvas && canvas.getContext && canvas.getContext('2d') ) ) {
      // ... redirection ...
    }
  </script>
  <script src="js/jquery.js"></script>
  <script>
    $(function () {
      //...
    }
  </script>

使用这些方法中的任何一种,执行顺序为:

  1. 第一个<script>
  2. 加载jquery.js,无论是使用document.write()还是使用简单的<script>代码。
  3. 最后的剧本。

答案 1 :(得分:3)

当您插入脚本标记时,它将在后台加载,而不是立即加载,因此您的下一个脚本将在加载jQuery之前运行。您将需要附加一个监听器,以便您知道何时成功加载了jQuery,然后您可以运行使用jQuery的脚本。

这篇文章描述了如何知道加载动态加载脚本的时间:http://software.intel.com/en-us/blogs/2010/05/22/dynamically-load-javascript-with-load-completion-notification


仅供参考,在您的具体情况下,您还可以拥有一个加载jQuery的静态脚本标记,但是将脚本检测是否在jQuery脚本标记之前重定向。那将是最简单的选择。

<script type="text/javascript">
    var canvas = document.createElement('canvas');
    if (!canvas || !canvas.getContext || !canvas.getContext('2d')) {
        // redirect here or whatever
    }
</script>
<script type="text/javascript" src="jquery.js">
</script>
<script type="text/javascript">
    $(function () {
      //...
    }
</script>

答案 2 :(得分:1)

终于像魅力一样工作,我松了一口气!

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>JS Bin</title>
   <script type="text/javascript">
      window.onload = function(){
        var jqu = "$(console.log('worked'));";
        var canvas = document.createElement('canvas');
        if (canvas && canvas.getContext && canvas.getContext('2d')) {
          var s = document.getElementsByTagName('head')[0];
          var jq = document.createElement('script');
          jq.setAttribute('type','text/javascript');
          jq.innerHTML = jqu;
          var jqLoad = document.createElement('script');
          jqLoad.setAttribute('type','text/javascript');
          jqLoad.setAttribute('src','jquery-1.10.0.js');
          jqLoad.setAttribute('id','jqloader');
          s.appendChild(jqLoad);
          document.getElementById('jqloader').onload = function(){
            console.log('loaded');
            s.appendChild(jq);
          }
        }
        else {
        // ... redirection ...
        }
        console.log(document);
      }
  </script>
</head>
<body>

</body>
</html>

<强> jsbin Demo

解释:

1-使用 dom函数来追加或插入元素总是最好的(动态且比其他任何东西更安全),并且不推荐使用document.write

2- 解析时间,您的脚本中的任何函数都将被评估,因此如果您有脚本并且尚未加载库,则会出现错误。

3-建议不要加载库并在同一标签中执行相关脚本。最好在另一个标签中脚本(完全加载完成后)以确保它能够正常工作。

document.onload的4个事件确保文档已加载 doms存在,因此可以将子项附加到它们。至于document.getElementById('jqloader').onload,只是为了确保 jquery库完全加载并添加到文档中,然后才会添加脚本并进行评估

答案 3 :(得分:0)

正如其他人所说,你收到错误的原因是因为你已经异步加载了jQuery而且它还没有加载。

有两种方法可以达到你想要的效果。

您可以轮询window.jQuery,也可以使用异步加载器回调。

由于您只在检测到画布支持时才加载jQuery,因此您不必担心支持旧浏览器。

var async_script_load = function (s, callback) {
    var script;

    script = document.createElement("script");
    script.async = "async";

    if (s.scriptCharset) {
        script.charset = s.scriptCharset;
    }

    script.src = s.url;

    // Attach handlers for all browsers
    script.onload = script.onreadystatechange = function () {
        if (!script.readyState || /loaded|complete/.test(script.readyState)) {
            // Handle memory leak in IE
            script.onload = script.onreadystatechange = null;

            // Remove the script
            if (head && script.parentNode) {
                head.removeChild(script);
            }

            // Dereference the script
            script = undefined;
            callback(200, "success");
        }
    };
    // Use insertBefore instead of appendChild  to circumvent an IE6 bug.
    // This arises when a base node is used (#2709 and #4378).
    head.insertBefore(script, head.firstChild);
};

async_loader({url:'http://tempuri.org/jquery.min.js'},function() {
   //call jquery here.
});

对于轮询方法,它就像:

一样简单
var checkJq = function() { 
    if(window.jQuery) {
      //do jQuery
    } else {
       setTimeout(checkJq,100);
    }
}

setTimeout(checkJq,100);