页面加载后加载脚本?

56

我在一家广告公司工作,我们会标记特定页面以跟踪活动。我的一个客户想要触发一个JavaScript标记来在页面完全加载后跟踪活动(以防止由于标记加载时间过慢而导致页面内容加载缓慢)。

应该在页面完全加载后加载的示例标记如下:

<script>document.write('<s'+'cript language="JavaScript" src="http://jact.atdmt.com/jaction/JavaScriptTest"></s'+'cript>')</script>

我在看一些stackoverflow的帖子时,发现了下面的实现方式,我认为它能够工作:

window.onload = function(){
  <script language="JavaScript" src="http://jact.atdmt.com/jaction/JavaScriptTest"></script>
};

我在自己的网页上测试过这个标签并且成功触发了它,但我想知道是否有其他替代方法或更加健壮的方法,最好使用 jQuery。

以下是客户尝试的样例实现,但似乎会破坏他们的页面:

<script>
jQuery(window).load(function () {$('<script language="JavaScript" src="http://jact.atdmt.com/jaction/JavaScriptTest"></script>').insertAfter('#div_name');});
</script>

我已经有一段时间没有用JQuery了,希望能从这里的其他成员得到一些意见。除了在页面加载后使用JQuery调用上述脚本之外,还有其他方法吗?

谢谢。


如果您正在使用jQuery,您只需执行$.getScript("urlHere")即可。但是,如果您正在制作广告,我建议您重新考虑一下是否使用jQuery - 因为它有80kb的代码量,这对于广告来说是非常大的。 - Benjamin Gruenbaum
这更像是一个1x1像素,可能会调用其他脚本。$.getScript会在页面上的所有内容加载完成后调用URL吗? - Kamui
您还可以在页面末尾添加您的脚本。 - Sylhare
请注意,命名空间函数将无法正常工作。例如,&callback=ns.init_gm&callback=ns%2Einit_gm将触发无效函数错误。&callback=google_maps_callback_cannot_use_namespaced_function不会触发错误。 - OXiGEN
请注意,命名空间函数将无法正常工作。例如,&callback=ns.init_gm&callback=ns%2Einit_gm 将触发无效函数错误。&callback=google_maps_callback_cannot_use_namespaced_function 不会触发错误。 - undefined
8个回答

110

所以,这样是行不通的:

window.onload = function(){
  <script language="JavaScript" src="http://jact.atdmt.com/jaction/JavaScriptTest"></script>
};

你不能随意将HTML代码嵌入到JavaScript中。


如果你有jQuery,你可以使用:

$.getScript("http://jact.atdmt.com/jaction/JavaScriptTest")

无论何时你想要。如果你想确保文档已经加载完成,你可以这样做:

$(document).ready(function() {
    $.getScript("http://jact.atdmt.com/jaction/JavaScriptTest");
});
在普通的 JavaScript 中,您可以像这样在任何时候动态加载脚本: ```html

在普通的JavaScript中,您可以使用以下代码动态加载脚本:

var tag = document.createElement("script");
tag.src = "http://jact.atdmt.com/jaction/JavaScriptTest";
document.getElementsByTagName("head")[0].appendChild(tag);

10
如果你想在异步加载的脚本文件加载完成后立即调用其中的函数,可以这样做:$.getScript('async.js', function() { my_function(); }); - Noel Whitemore
3
getScript 不会使用浏览器缓存。这将重新加载文件并需要一些时间。 - Iññoceñt Ùšmâñ
脚本加载后有没有办法执行某些操作?直接在加载脚本之后执行会导致脚本尚未加载完成。(使用纯JS,不使用jQuery。) - mcv
你说得对。我的问题在这个问题中得到了解决:https://dev59.com/yGUq5IYBdhLWcg3wQ-Tk。虽然那并没有完全解决它,因为我正在加载Youtube API,当回调触发时,它显然还没有完全初始化,所以它提供了自己的硬编码回调函数onYouTubeIframeAPIReady() - mcv
@mcv - 是的,那绝对适合这个混合。如果库本身在加载后执行一些操作(例如可能会动态加载组件),那么您必须在脚本本身加载后使用它的onload API(无论它是什么)。 - jfriend00
显示剩余3条评论

13

我为一个渐进式Web应用程序编写了一个脚本,可以轻松地异步按需加载JavaScript文件。脚本只会被加载一次。因此,您可以随时多次调用loadScript来加载同一文件,它不会被重复加载。此脚本需要JQuery才能正常工作。

例如:

loadScript("js/myscript.js").then(function(){
    // Do whatever you want to do after script load
});

或者在异步函数中使用:

await loadScript("js/myscript.js");
// Do whatever you want to do after script load
在您的情况下,您可以在文档准备就绪后执行这个操作:
$(document).ready(async function() {
    await loadScript("js/myscript.js");
    // Do whatever you want to do after script is ready
});

loadScript函数:

function loadScript(src) {
  return new Promise(function (resolve, reject) {
    if ($("script[src='" + src + "']").length === 0) {
        var script = document.createElement('script');
        script.onload = function () {
            resolve();
        };
        script.onerror = function () {
            reject();
        };
        script.src = src;
        document.body.appendChild(script);
    } else {
        resolve();
    }
});
}

这种方法的好处:

  • 它使用浏览器缓存
  • 您可以在用户执行需要该脚本的操作时加载脚本文件,而不是总是加载它。

2
不错!但是在这里使用纯JavaScript会更好,为什么要在这里使用jQuery呢?例如,将if()替换为document.querySelector("script[src='" + src + "']") === null。 - user706420

11

第二种方法是在页面加载完成后执行JavaScript代码的正确方法 - 但实际上你没有执行JavaScript代码,而是插入了普通的HTML。
第一种方法可以工作,但会立即加载JavaScript并清空页面(因此你的标签会在那里,但没有其他内容)。
(另外:language="javascript"已经被弃用多年了,请改用type="text/javascript"!)

要让它起作用,你需要使用JavaScript中包含的DOM操作方法。基本上你需要这样做:

var scriptElement=document.createElement('script');
scriptElement.type = 'text/javascript';
scriptElement.src = filename;
document.head.appendChild(scriptElement);

如果在文档加载完成后使用 document.write(),它将清除当前文档并开始一个新文档,这肯定不是 OP 想要的。 - jfriend00
哦,你当然是对的!我会编辑我的答案以反映这一点。 - Johannes H.

9

4
我不明白为什么这不是正确且最简单的解决方案! - Broken Arrow
1
对我来说有点误导。脚本仍将在onload之前下载,但只有在此后才会执行。就像作者一样,我也希望在onload事件触发之前不阻止资源。 - Moseleyi

6

聚焦于 已被接受的答案 中的一个 jQuery 解决方案,$.getScript() 是一个伪装成 .ajax() 请求的方法。它允许通过添加第二个参数在成功时执行其他函数:

$.getScript(url, function() {console.log('loaded script!')})

或者在请求处理程序本身上,即成功(.done() - 脚本已加载)或失败(.fail()):

$.getScript(
    "https://code.jquery.com/color/jquery.color.js",
    () => console.log('loaded script!')
  ).done((script,textStatus ) => {
    console.log( textStatus );
    $(".block").animate({backgroundColor: "green"}, 1000);
  }).fail(( jqxhr, settings, exception ) => {
    console.log(exception + ': ' + jqxhr.status);
  }
);
.block {background-color: blue;width: 50vw;height: 50vh;margin: 1rem;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="block"></div>


1
注意:默认情况下,$.getScript() 不利用浏览器缓存,并且总是从服务器加载完整的脚本。 - Philipp

2

这是我正在使用的代码,对我来说它很有效。

原始答案翻译成“最初的回答”。

window.onload = function(){
    setTimeout(function(){
        var scriptElement=document.createElement('script');
        scriptElement.type = 'text/javascript';
        scriptElement.src = "vendor/js/jquery.min.js";
        document.head.appendChild(scriptElement);

        setTimeout(function() {
            var scriptElement1=document.createElement('script');
            scriptElement1.type = 'text/javascript';
            scriptElement1.src = "gallery/js/lc_lightbox.lite.min.js";
            document.head.appendChild(scriptElement1);
        }, 100);
        setTimeout(function() {
            $(document).ready(function(e){
                lc_lightbox('.elem', {
                    wrap_class: 'lcl_fade_oc',
                    gallery : true, 
                    thumb_attr: 'data-lcl-thumb', 
                    slideshow_time  : 3000,
                    skin: 'minimal',
                    radius: 0,
                    padding : 0,
                    border_w: 0,
                }); 
            });
        }, 200);

    }, 150);
};

0

<script type="text/javascript">
$(window).bind("load", function() { 

// your javascript event

)};
</script>


此回答缺少教育性的解释。 - mickmackusa

-1

http://jsfiddle.net/c725wcn9/2/embedded

您需要检查DOM以确保此功能正常工作。需要使用Jquery。
$(document).ready(function(){
   var el = document.createElement('script');
   el.type = 'application/ld+json';
   el.text = JSON.stringify({ "@context": "http://schema.org",  "@type": "Recipe", "name": "My recipe name" });

   document.querySelector('head').appendChild(el);
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接