通过DOM插入执行javascript [英] Executing javascript loaded via DOM insertion

查看:167
本文介绍了通过DOM插入执行javascript的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一些可以将客户端添加到客户站点的东西,我想异步加载我的js,以免阻止客户的页面加载。我一直在阅读很多关于这个的线程,并且一直试图实现这里建议的模式,因为我的项目非常相似:

I'm working on something that will add a widget to a customer's site, and I want to load my js asynchronously so as not to block the customer's page loading. I've been reading a lot of threads about this, and have been trying to implement the pattern suggested here as my project is very similar:

http://friendlybit.com/js/lazy-loading-asyncronous-javascript

我的问题是我动态加载的javascript文件中的代码不会被执行。对不起,如果这似乎是一个重复的问题,但我花了几个小时搜索和尝试略有不同的技术,我已经阅读了许多帖子,包括这些stackoverflow问题:

The problem I have is the code in my dynamically-loaded javascript file just doesn't get executed. Sorry if this seems to be a duplicate question, but I've spent hours searching and trying slightly different techniques, and I've read numerous posts including these stackoverflow questions:

  • Load javascript async, then check DOM loaded before executing callback
  • Load jQuery in a js, then execute a script that depends on it
  • Loading scripts dynamically

但我仍然努力使这项工作,所以我希望如果我问这个问题直接有人可能可以帮助我!

but I'm still struggling to make this work, so I was hoping if I ask the question directly someone here might be able to help me out!

我' ve目前得到以下作为一个真正的基础美东时间;显然在我的真实脚本中还有很多事情要做,但是我只需要了解这里发生了什么(或者实际上没有发生什么)。

I've currently got the following as a really basic test; obviously there's a lot more going on in my real script, but I just need to understand what's happening here (or, in fact, what's not happening).

所以在我的代码文件test.js我只需要:

So in my code file "test.js" I simply have:

run_test = function () {
    alert('hello from test');
};

然后在我有的页面上:

(function () {
     load_test = function () {
        var t = document.getElementsByTagName('script')[0];
        var s = document.createElement('script');
        s.type = 'text/javscript';
        s.async = true;
        s.src = 'test.js';

        s.onload = s.readystatechange = function () {
            if (run_test) run_test();

            s.onload = null;
            s.onreadystatechange = null;
        };

        t.parentNode.insertBefore(s, t);
    };

    load_test();
})();

我已经尝试了几种变体 - 我尝试删除s.async = true 只是看看它是否有所作为,但是它不会。我原来有以下代码,而不是load_test();,正如我提到的第一篇文章中所提到的:

I've already tried several variations on this - I've tried removing "s.async = true" just to see if it makes a difference, but it doesn't. I originally had the following instead of "load_test();", as suggested in the first post I mentioned:

window.attachEvent ? window.attachEvent('onload', load_test) : window.addEventListener('load', load_test, false);

但结果总是一样的,我从来没有看到消息hello from test。实际上,我甚至可以在load_test函数中发出警报 - 如果我在s.onload = s.readystatechange ..之前发出警报,我看到该消息,但该onload函数中的警报不会出现。所以看起来动态添加的脚本的onload从不会触发。

but the result is always the same, I never see the message "hello from test". In fact I can even put alerts in the load_test function - if I put an alert just before the line "s.onload = s.readystatechange .." I see that message, but an alert within that onload function never appears. So it would appear that the dynamically added script's onload never fires.

BTW作为一个旁边 - 可能或可能不相关,但是我通常在Firefox中测试,如果我看看firebug中的html,我看到test.js脚本已经被加载,但是如果我展开该节点,我只是看到消息重新加载页面以获取...的源。无论我重新加载页面多少次,我看不到代码。我已经在其他浏览器中尝试了相同的测试结果。

BTW as an aside - may or may not be relevant, but I generally test in Firefox, and if I look at the html in firebug, I see the test.js script has been loaded, but if I expand that node I just see the message "Reload the page to get source for ...". Doesn't matter how many times I reload the page, I can't see the code. I have tried testing in other browsers with the same results.

不能感到我在这里缺少一些基本的东西;任何帮助将非常感谢!

Can't help feeling I'm missing something fundamental here; any help would be very much appreciated!

Pete

感谢所有的输入。

@zzzzBov,感谢这个例子,虽然我不知道我完全理解了 - 我以为onload会一次火脚本完成加载,就像将代码附加到页面的onload事件相同。我对onreadystatechange的理解是,它只是在IE中捕获相同的东西。

@zzzzBov, thanks for the example, although I'm not sure I completely understand still - I thought that "onload" would fire once after the script finishes loading, in the same way as attaching code to the onload event of the page. My understanding of "onreadystatechange" was that it was just to catch the same thing in IE.

为了回应你的意见,新的脚本被插入到在原始脚本块之前的页面(带有insertBefore语句)(假定原始脚本块在头部,它是)。

In response to your comments, the new script is inserted in the head of the page (with the insertBefore statement) right before the original script block (assuming the original script block is in the head, which it is).

关于测试。 js路径,我省略了路径,只是为了简化示例。我的脚本路径绝对正确;我可以通过firebug看到脚本实际上被添加到头上。

With regard to the test.js path, I omitted the path just to simplify the example. My path to the script is definitely correct; I can see via firebug that the script is actually added (to the head).

我的问题是,在脚本加载之后,它根本无法运行,但是我认为我实际上是碰到一些缓存问题,因为我已经使用在我上面发布的第一个链接中描述的模式(这里是一个很好的措施: http ://friendlybit.com/js/lazy-loading-asyncronous-javascript/ )。

My problem was that after the script loaded, it simply failed to run, but I think I was actually hitting some caching problems as I've since got this working using the pattern described in the first link I posted above (here it is again for good measure: http://friendlybit.com/js/lazy-loading-asyncronous-javascript/).

所以我的代码是这样的:

So my code is something like this:

(function () {
    var addscript = function () {
        var h = document.getElementsByTagName('head')[0],
            s = document.createElement('script');
        s.type = "text/javascript";
        s.async = true;
        s.src = "myscript.js";
        h.appendChild(s);
    };
    window.attachEvent ? window.attachEvent('onload', addscript) : 
        window.addEventListener('load', addscript, false);
})();

如果您检查该帖子的评论,我认为这是解释为什么这是一个好主意,包括s.async = true,即使在这种情况下脚本附加到窗口onload事件。

If you check the comments on that post, I think it's explained somewhere why it's a good idea to still include "s.async = true" even though in this case the script is attached to the window onload event.

我的真实主脚本确实需要jQuery,所以我认为我的最终解决方案将是使用这样的东西加载jQuery,然后一旦我知道这是加载,让jQuery做加载任何我需要的其他脚本的工作。

My "real" main script does actually require jQuery, so I think my eventual solution will be to use something like this to load jQuery, then once I know that's loaded, let jQuery do the work of loading any other scripts I need.

再次感谢您的帮助。

Pete

推荐答案

你的脚本有几个问题。这是一个应该工作的应用程序。

You've got a few issues with your script. Here's one that should work.

function loadScript(src, callback)
{
  var s, r;
  r = false;
  s = document.createElement('script');
  s.type = 'text/javascript';
  s.src = src;
  s.onload = s.onreadystatechange = function() {
    //console.log( this.readyState ); //uncomment this line to see which ready states are called.
    if ( !r && (!this.readyState || this.readyState == 'complete') )
    {
      r = true;
      callback();
    }
  };
  document.body.appendChild(s);
}

您的 load_test 函数是在新脚本执行之前调用 run_test()。您的脚本将删除 onload onreadystatechange 事件回调在第一个 onreadystatechange 事件通常是加载

The issue with your load_test function is that it'll call run_test() before the new script has executed. Your script will remove the onload and onreadystatechange event callbacks at the first onreadystatechange event which is typically loading.

另外, async 应该是不必要的,因为新添加的脚本将被插入到 document.body 的末尾。如果要在页面的其余部分后加载脚本,请等待页面的其余部分加载( body.onload 调用 loadScript 之前的document.onreadystatechange

Also, async should be unnecessary, as the newly added script will be inserted at the end of the document.body wherever that may be. If you'd like to load the script after the rest of the page, then wait for the rest of the page to load (body.onload or document.onreadystatechange) before calling loadScript.

脚本声音最大的问题像 test.js 在被调用的路径上不存在。确保添加< script type =text / javascriptsrc =test.js>< / script> inline实际工作。

The biggest issue with your script sounds like test.js doesn't exist at the path it's being called. Make sure that adding <script type="text/javascript" src="test.js"></script> inline actually works.

这篇关于通过DOM插入执行javascript的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆