【问题标题】:jQuery append will download external src in script tags, but won't load into DOMjQuery append 将下载脚本标签中的外部 src,但不会加载到 DOM
【发布时间】:2015-07-01 21:08:41
【问题描述】:

如果我包含一个带有外部源的脚本,然后尝试使用 jQuery 进行解析 - 它会下载该脚本,但不会将其加载到 DOM 中。我正在使用 .append(),但这似乎适用于任何其他 jQuery DOM 插入方法。

这是 Stack Snippets 中的一个示例

$(function(){
  
  var selet2Html =
    '<link href="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.css" rel="stylesheet"/>' +
    '<script src="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.js" ><\/script>' +
    '<select class="select2">' +
    '  <option value="AK">Alaska</option>' +
    '  <option value="HI">Hawaii</option>' +
    '</select>' +
    '<script >' +
    '  $(function() {' +
    '    $(".select2").select2();' +
    '  });' +
    '<\/script>';
    
  $("body").append(selet2Html);
  
});
&lt;script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"&gt;&lt;/script&gt;

即使这会在网络选项卡中下载脚本:

它仍然会返回以下错误(表明外部库-select2-从未加载):

我不想使用$.getScript(),因为我实际上是使用.load() 动态加载这个字符串,所以我不确定它是否会包含任何外部脚本。

如何让它加载外部库?

【问题讨论】:

  • 使用前需要给它时间加载,动态标签不像硬编码标签那样同步
  • 是的,这是一个简单的竞争条件。您需要等待$.fn.select2 出现。
  • 据我所知,.getScript().load() 都不会告诉您加载的脚本何时执行。他们的回调在文件加载并且不需要执行时触发。我建议您将代码拆分为不同的部分,您将附加.when() 每个部分是.done()
  • 你考虑过使用 $.holdready 吗? api.jquery.com/jQuery.holdReady

标签: javascript jquery dom src script-element


【解决方案1】:

所以 dandavis 是对的 - 库需要时间来加载,然后再调用它的初始化程序。一个幼稚的实现可能只是等待一小段时间,然后再试一次,如下所示:

setTimeout( function() {
  $(".select2").select2();
}, 2000);

堆栈片段中的简单演示:

$(function(){
  
  var selet2Html =
    '<link href="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.css" rel="stylesheet"/>' +
    '<script src="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.js" ><\/script>' +
    '<select class="select2">' +
    '  <option value="AK">Alaska</option>' +
    '  <option value="HI">Hawaii</option>' +
    '</select>' +
    '<script >' +
    '  setTimeout( function() {' +
    '    $(".select2").select2();' +
    '  }, 2000);' +
    '<\/script>';
   
  $("body").append(selet2Html);
  
});
&lt;script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"&gt;&lt;/script&gt;

更复杂的解决方案是等到$.fn.select2 出现在 DOM 中。

输入OnAvailable

你可以这样称呼它:

onAvailable('$.fn.select2', function() {
  alert('we did it');
});

这里的函数将轮询全局命名空间以使您的变量弹出。它使用来自 Accessing nested JavaScript objects with string key 的 Alnitak 的 Object.byString 解决方案

function onAvailable(listenFor, callback) {
  var interval = window.setInterval(function() {
    if (Object.byString(window, listenFor)) {
      clearInterval(interval);
      callback()
    }
  }, 100);
};

堆栈片段中的高级演示

function onAvailable(listenFor, callback) {
  var interval = window.setInterval(function() {
    if (objectFromString(window, listenFor)) {
      clearInterval(interval);
      callback()
    }
  }, 100);
};

function objectFromString(o, s) {
  s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
  s = s.replace(/^\./, '');           // strip a leading dot
  var a = s.split('.');
  for (var i = 0, n = a.length; i < n; ++i) {
    var k = a[i];
    if (k in o) {
      o = o[k];
    } else {
      return;
    }
  }
  return o;
}

$(function(){
  
  var selet2Html =
    '<link href="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.css" rel="stylesheet"/>' +
    '<script src="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.js" ><\/script>' +
    '<select class="select2">' +
    '  <option value="AK">Alaska</option>' +
    '  <option value="HI">Hawaii</option>' +
    '</select>' +
    '<script >' +
    '  onAvailable("$.fn.select2", function() {' +
    '    $(".select2").select2();' +
    '  });' +
    '<\/script>';
   
  $("body").append(selet2Html);
  
  
});
&lt;script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"&gt;&lt;/script&gt;

【讨论】:

    猜你喜欢
    • 2016-03-20
    • 2011-10-02
    • 1970-01-01
    • 1970-01-01
    • 2021-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多