5

如果浏览器似乎支持 HTML5,我正在使用纯 JavaScript 进行测试,如果支持,我想加载 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

4 回答 4

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. 最后的剧本。
于 2013-07-04T03:13:05.703 回答
3

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

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


仅供参考,在您的特定情况下,您也可以只有一个加载 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>
于 2013-07-04T03:13:14.737 回答
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 演示

解释 :

1- 使用dom 函数来追加或插入元素始终是最好的(动态且比其他任何东西都更安全),document.write因此不建议这样做。

2- 在解析时,脚本中的任何函数都将被评估,因此如果您有脚本但尚未加载库,则会收到错误消息。

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

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

于 2013-07-04T04:23:26.240 回答
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);
于 2013-07-04T03:44:24.953 回答