简体   繁体   English

在js中加载jQuery,然后执行依赖于它的脚本

[英]Load jQuery in a js, then execute a script that depends on it

I have a unique issue - 我有一个独特的问题 -

I am designing a web application that creates widgets that a user can then embed in their own page (blog posts, mostly). 我正在设计一个创建小部件的Web应用程序,然后用户可以将这些小部件嵌入到他们自己的页面中(主要是博客文章)。 I want them to just have to embed one line, so I just had that line be an include statement, to pull a Javascript off my server. 我希望他们只需要嵌入一行,所以我只是将该行作为include语句,从我的服务器上取下Javascript。

The problem is, I am building the widget code using jQuery, and I need to load the jQuery plugin, since I obviously don't know whether or not my users will have it available. 问题是,我正在使用jQuery构建窗口小部件代码,我需要加载jQuery插件,因为我显然不知道我的用户是否可以使用它。 I thought 'this should be pretty simple'.... 我想'这应该很简单'......

function includeJavaScript(jsFile) {
  var script = document.createElement('script');
  script.src = jsFile;
  script.type = 'text/javascript';
  document.getElementsByTagName('head')[0].appendChild(script);
}

includeJavaScript('http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js');
jQuery();

So, I am appending the jQuery file to the head, then afterwards, trying to run a jQuery function. 所以,我将jQuery文件附加到头部,然后尝试运行jQuery函数。 Trouble is, this doesn't work! 麻烦的是,这不起作用! Everytime I run it, I get the error that variable jQuery is not defined. 每次运行它时,我都会收到错误,即未定义变量jQuery。 I have tried a few things. 我尝试了一些事情。 I tried putting the jQuery functions in an onLoad trigger, so that the whole page (including, presumably, the jQuery file) would load before it called my script. 我尝试将jQuery函数放在onLoad触发器中,以便整个页面(包括,可能是jQuery文件)在调用我的脚本之前加载。 I tried putting the jQuery function in a seperate file, and loading it after loading the jQuery lib file. 我尝试将jQuery函数放在一个单独的文件中,并在加载jQuery lib文件后加载它。 But I get the idea I'm missing something simple - I'm new to jQuery, so if I'm missing something obvious, I apologize... 但是我觉得我错过了一些简单的东西 - 我是jQuery的新手,所以如果我遗漏了一些明显的东西,我道歉......

EDIT 编辑

OK,I tried the suggestion offered by digitalFresh, as follows (using Safari 5, if that helps), but I still get the same error? 好的,我尝试了digitalFresh提供的建议,如下(使用Safari 5,如果有帮助),但我仍然得到相同的错误?

function test() {
    jQuery()
}

var script = document.createElement("script");
script.type = "text/javascript";
script.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js';
script.onload = test(); //execute
document.body.appendChild(script);

EDIT 编辑

OK, I FINALLY got it to work, in an offhand suggestion from Brendan, by putting the call ITSELF in an 'onload' handler, like so: 好吧,我最终通过Brendan的一个随意的建议让它工作,将调用ITSELF放在'onload'处理程序中,如下所示:

function addLoadEvent(func) { 
      var oldonload = window.onload; 
      if (typeof window.onload != 'function') { 
        window.onload = func; 
      } else { 
        window.onload = function() { 
          if (oldonload) { 
            oldonload(); 
          } 
          func(); 
        } 
    } 
} 
addLoadEvent( function() {
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js';
    document.body.appendChild(script);
    jQuery();
});

At this point, as you can see, I don't even have to put it in an 'onload' - it just works. 在这一点上,正如你所看到的,我甚至不必把它放在'onload'中 - 它只是起作用。 Though I have to admit, I still don't understand WHY it works, which bothers me... 虽然我不得不承认,我仍然不明白为什么它有效,这让我感到困扰......

The solution you end up using works but slow to start , and not 100% fail proof . 您最终使用的解决方案有效,但启动缓慢 ,而不是100%失败证明 If someone rewrites window.onload your code will not run. 如果有人重写window.onload你的代码将无法运行。 Also window.onload happens when all the content on the page is loaded (including images) which is not exactly what you want. 当载入页面上的所有内容(包括图像)时,也会发生window.onload,这并不是您想要的。 You don't want your script to wait that long. 您不希望脚本等待那么久。

Fortunately <script> elements have their own onload (ready) event , which can be used to couple other scripts with them. 幸运的是, <script>元素有自己的onload(ready)事件 ,可用于将其他脚本与它们耦合。

function include(file, callback) {
  var head      = document.getElementsByTagName('head')[0];
  var script    = document.createElement('script');
  script.type   = 'text/javascript';
  script.src    = file;
  script.onload = script.onreadystatechange = function() {
    // execute dependent code
    if (callback) callback();
    // prevent memory leak in IE
    head.removeChild(script);
    script.onload = null;
  };
  head.appendChild(script);
}

include('http://ajax.googleapis.com/.../jquery.min.js', myFunction);

In this case the function will be called exactly when jquery is available. 在这种情况下,当jquery可用时,将完全调用该函数。 Your code is fail proof and starts quickly. 您的代码是失败证明并快速启动。

The script is not loaded or executed when you call the jQuery function. 调用jQuery函数时,不会加载或执行脚本。 Thats why you get the error that jQuery is not defined. 这就是为什么你得到jQuery没有定义的错误。

I answered this problem on Loading Scripts Dynamically . 我在动态加载脚本时回答了这个问题。 The script is simple for all browsers except IE. 除了IE之外,所有浏览器的脚本都很简单。 Just add an onload event listener 只需添加一个onload事件监听器

If you're using jQuery, you can use getScript() . 如果您使用的是jQuery,则可以使用getScript() Facebook has a good example on how to employ this . Facebook有一个很好的例子来说明如何使用它 This is a more manageable solution to the original one I posted below. 对于我在下面发布的原始版本,这是一个更易于管理的解决方案。

Alternatively: 或者:

Building off of galambalazs's answer you can wrap his include() function in an event like the jQuery $(document).ready() to create deferred scripts with a dependency line without having to rely on an extra JS plugin. 基于galambalazs的答案,你可以将他的include()函数包装在像jQuery $(document).ready()这样的事件中,以创建具有依赖行的延迟脚本,而不必依赖额外的JS插件。 I also added a callbackOnError, which is handy if you're fetching from Google CDN. 我还添加了一个callbackOnError,如果你是从谷歌CDN获取的话,这很方便。

/* galambalazs's include() */
function include(file, callback, callbackOnError) {
    var head      = document.getElementsByTagName('head')[0];
    var script    = document.createElement('script');
    script.type   = 'text/javascript';
    script.src    = file;
    script.onload = script.onreadystatechange = function() {
      // execute dependent code
      if (callback) callback();
      // prevent memory leak in IE
      head.removeChild(script);
      script.onload = null;
      script.onerror = null;
    };
    script.onerror = function() {
      if(callbackOnError) callbackOnError();
      // prevent memory leak in IE
      head.removeChild(script);
      script.onload = null;
      script.onerror = null;
    };
    head.appendChild(script);
 }

/* If you need a deferred inline script, this will work */
function init() {
    // Insert Code
}

/* Example with callback */
$(document).ready(function() {
    include('something.js', init);
});

/* Maybe I want something on window.load() */
$(window).load(function() {
    // Without a callback
    include('whatever.js');
});

/* Or use an event to load and initialize script when it's needed */
$(".nearAButton").hover(include('button.js',function() {initButtonJS()}));

function initButtonJS() {
    $(".nearAButton").off("mouseenter mouseleave");
}

/* Attempt to load Google Code, on fail load local */
include(
    '//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js',
    function () {
        // Inline Callback
    },
    function () {
        include('/local/jquery-ui-1.10.3.custom.min.js', function () {
            // Inline Callback
        });
    }
);

Use LABjs . 使用LABjs Embedding <script> tags work because the browser loads and executes whatever script in it or referenced by it upon seeing any of them, but that also means the browser will block until it is done with the script. 嵌入<script>标签是有效的,因为浏览器加载并执行其中的任何脚本或在看到它们时引用它们,但这也意味着浏览器将阻塞,直到完成脚本。

You should first check to make sure they do not already use jquery so something like: 您应首先检查以确保它们尚未使用jquery,例如:

if (jQuery) {  
    // jQuery is loaded  
} else {
    // jQuery is not loaded
}

Secondly, you should make sure you use jQuery in no conflict mode and do not use the $ operator as it may be claimed by another script library. 其次,您应该确保在没有冲突模式下使用jQuery,并且不要使用$运算符,因为它可能由另一个脚本库声明。

Then to embed, declare this function: 然后嵌入,声明这个函数:

function load_script (url)
 {
   var xmlhttp;
   try {
     // Mozilla / Safari / IE7
     xmlhttp = new XMLHttpRequest();
    } catch (e) {
      //Other IE
      xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
    }
    xmlhttp.open('GET', url, false); x.send('');
    eval(xmlhttp.responseText);
    var s = xmlhttp.responseText.split(/\n/);
    var r = /^function\s*([a-z_]+)/i; 

      for (var i = 0; i < s.length; i++)
      {
          var m = r.exec(s[i]);
          if (m != null)
              window[m[1]] = eval(m[1]);
      }
  } 

Then call it: 然后叫它:

load_script('http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js');

Hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM