为什么DOM appendChild()会触发('load',...)但是jQuery append()却没有?

时间:2014-10-27 01:05:42

标签: javascript jquery dom onload

我有以下代码片段:

$(document).ready(function() {
    document.head.appendChild(
        $('<script />').attr('src', 'source.js').on('load', function() {
            ...
        })[0]
    );
});

这将触发加载程序。

使用普通的jQuery append()

$(document).ready(function() {
   $('head').append(
        $('<script />').attr('src', 'source.js').on('load', function() {
            ...
        })
    );
});

这不会解雇负荷人。

我缺少什么:为什么jQuery append()不起作用?

使用document.head.appendChild()是个坏主意吗?

注意:我无法使用$.getScript()。代码将在本地文件系统上运行,并且chrome会引发跨站点脚本错误。


更新

有些人在阅读紧凑风格时遇到了麻烦,所以我使用了额外的换行来澄清调用哪些方法的对象。我还明确表示我的代码位于$(document).ready块内。


解决方案

最后,我选择了:

$(document).ready(function() {
    $('head')[0].appendChild(
        $('<script />').attr('src', 'source.js').on('load', function() {
            …
        })[0]
    );
});

我认为@istos是正确的,domManip中的内容正在打破load

4 个答案:

答案 0 :(得分:1)

jQuery在其DOM操作代码中做了一些有趣的事情。如果你看一下jQuery的源代码,你会发现它在domManip()方法中使用了一个名为append()的方法。

这个domManip()方法创建了一个文档片段(看起来节点首先被附加到&#34; safe&#34;片段),并且有很多检查和条件关于脚本。我不确定为什么它使用文档片段或为什么存在关于脚本的所有检查,但是使用原生appendChild()而不是jQuery&#39; append()方法成功激活事件。这是代码:

直播JSBin:http://jsbin.com/qubuyariba/1/edit

  var url = 'http://d3js.org/d3.v3.min.js';  
  var s = document.createElement('script');
  s.src = url;
  s.async = true;

  $(s).on('load', function(e) {
    console.log(!!window.d3); // d3 exists
    $(document.body).append('<h1>Load fired!</h1>');
  });

  $('head').get(0).appendChild(s);


更新

appendChild()是一种受到良好支持的方法,在这种情况下绝对没有理由不使用它。

答案 1 :(得分:0)

也许问题是当你选择DOM appendChild时,实际上你调用的函数是document.on('load',function(){});,但是当你选择jQuery append()时,你的代码是$('head').on('load', function(){})

documenthead不同。

您可以输入以下代码: $(document).find('head').append($('<script />').attr('src', 'source.js').end().on('load', function() { ... }));

答案 2 :(得分:0)

您应该确保在文档准备好时触发jquery追加。当附加物发射时,头部实际上可能不在dom中。

答案 3 :(得分:0)

你不必完全抛弃jquery,你可以使用zeptojs。其次,我无法确定这种行为是如何以及为何发生的。即使我觉得答案可以在下面的链接中找到。到目前为止,我可以告诉你,如果你在definig src元素之前插入元素,那么load将不会触发。

但是对于手动插入并不重要。 (????)

然而,我能够发现的是,如果你使用appendTo它就可以了。 代码: http://jsfiddle.net/techsin/tngxnkk7/

var $ele = $('<script />').attr('src', link).load(function(){ abc(); }) ).appendTo('head');

新信息:据了解,将脚本标签添加到带有src属性的dom上,启动src中提到的脚本的下载过程。手动插入会导致页面加载外部脚本,使用appendappendTo会导致jquery启动外部js文件的下载。但事件是使用jquery附加,jquery启动下载然后事件将不会触发。但如果它是页面本身启动下载,那么它。即使事件是手动添加的,没有jquery,通过jquery添加到dom也不会触发它。

我认为应该是答案的链接...

Append Vs AppendChild JQuery

http://www.blog.highub.com/javascript/decoding-jquery-dommanip-dom-manipulation/

http://www.blog.highub.com/javascript/decoding-jquery-dommanip-dom-manipulation/

https://github.com/jquery/jquery/blob/master/src/manipulation.js#L477-523

http://ejohn.org/blog/dom-documentfragments/