jQuery append将在脚本标记中下载外部src,但不会加载到DOM中

时间:2015-06-30 20:31:12

标签: javascript jquery dom src script-element

如果我使用外部源包含脚本然后尝试使用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);
  
});
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>

即使这会在网络标签中下载脚本:

Network Activity

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

Uncaught TypeError: $(...).select2 is not a function

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

如何让它加载外部库?

1 个答案:

答案 0 :(得分:0)

所以dandavis是对的 - 在调用初始化程序之前,库需要时间加载。一个天真的实现可能只是等待很短的时间,并再试一次:

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

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 >' +
    '  setTimeout( function() {' +
    '    $(".select2").select2();' +
    '  }, 2000);' +
    '<\/script>';
   
  $("body").append(selet2Html);
  
});
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>

更复杂的解决方案会等到$.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);
};

Stack Snippets中的高级演示

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);
  
  
});
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>