65

在我的页面正文中,我需要插入此代码作为 AJAX 调用的结果:

    <p>Loading jQuery</p>
    <script type='text/javascript' src='scripts/jquery/core/jquery-1.4.4.js'></script>
    <p>Using jQuery</p>
    <script type='text/javascript'>
        $.ajax({
            ...
        });
    </script>

我无法使用$.load(),因为文档已经加载,所以事件不会触发。

这安全吗?如果没有,我如何确保在执行我的自定义生成代码之前已加载 jquery 脚本。

4

8 回答 8

83

向您的脚本文件添加一个 ID,以便您可以查询它。

<script id="hljs" async src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.0.0/highlight.min.js"></script>

然后在 JavaScript 中为它添加一个负载监听器

<script>
  var script = document.querySelector('#hljs');
  script.addEventListener('load', function() {
    hljs.initHighlightingOnLoad(); 
  });
</script>
于 2017-03-28T17:43:42.537 回答
46

这是相当安全的。从历史上看,<script>标签是完全阻塞的,因此<script>在前者完成解析/执行之前无法遇到第二个标签。唯一的问题可能是“现代”浏览器倾向于异步和延迟加载脚本。因此,为了确保顺序正确,请像这样使用它:

<p>Loading jQuery</p>
<script type='text/javascript' async=false defer=false src='scripts/jquery/core/jquery-1.4.4.js'></script>
<p>Using jQuery</p>
<script type='text/javascript'>
    $.ajax({
        ...
    });
</script>

但是,使用动态脚本标签插入而不是将其作为 HTML 字符串推送到 DOM 可能是一个更好的主意。会是同一个故事

var scr  = document.createElement('script'),
    head = document.head || document.getElementsByTagName('head')[0];
    scr.src = 'scripts/jquery/core/jquery-1.4.4.js';
    scr.async = false; // optionally

head.insertBefore(scr, head.firstChild);
于 2011-09-05T13:46:05.943 回答
21
const jsScript = document.createElement('script')
jsScript.src =
  'https://coolJavascript.js'

document.body.appendChild(jsScript)

jsScript.addEventListener('load', () => {
  doSomethingNow()
})

动态添加脚本后会加载

于 2019-11-25T23:03:50.773 回答
11

中也有新功能jQuery 1.6。它被称为jQuery.holdReady()。它实际上是不言自明的;当你打电话时jQuery.holdReady(true),在你打电话ready之前不会触发事件jQuery.holdReady(false)。将此设置为 false 将不会自动触发就绪事件,它只会删除保留。

这是一个从文档中加载脚本的非阻塞示例:

$.holdReady(true);
$.getScript("myplugin.js", function() {
     $.holdReady(false);
});

有关更多信息,请参阅http://api.jquery.com/jQuery.holdReady/

于 2011-09-05T20:50:17.417 回答
11

等待多个脚本加载

以下帮助程序仅加载多个脚本一次并返回一个承诺:

async function cirosantilli_load_scripts(script_urls) {
    function load(script_url) {
        return new Promise(function(resolve, reject) {
            if (cirosantilli_load_scripts.loaded.has(script_url)) {
                resolve();
            } else {
                var script = document.createElement('script');
                script.onload = resolve;
                script.src = script_url
                document.head.appendChild(script);
            }
        });
    }
    var promises = [];
    for (const script_url of script_urls) {
        promises.push(load(script_url));
    }
    await Promise.all(promises);
    for (const script_url of script_urls) {
        cirosantilli_load_scripts.loaded.add(script_url);
    }
}
cirosantilli_load_scripts.loaded = new Set();

(async () => {
    await cirosantilli_load_scripts([
        'https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.min.js',
        'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js',
    ]);

    // Now do stuff with those scripts.

})();

GitHub 上游:定义使用

经过铬 75 测试。

于 2019-07-30T08:37:37.663 回答
1

就我而言,解决方案不起作用。我想在脚本加载链接的右键单击事件后以编程方式单击链接。因此我不得不使用超时和循环:

<script>
  var ifrbutton = document.getElementById("id-of-link");
  if(typeof(ifrbutton) != 'undefined' && ifrbutton != null && window.location.hash == "#special-hash") {
    var i = 0;
    // store the interval id to clear in future
    var intr = setInterval(function() {
      if (ifrbutton.onclick!=null) {
        ifrbutton.click();
        clearInterval(intr);
        i = 200;
      }
      if (++i >= 200) clearInterval(intr);
    }, 300)
  }
</script>

因此,解决方案也可能是检查脚本带来的某些功能的间隔......设置一些安全的结束,以防脚本永远不会加载......对我来说安全工作;)

于 2021-08-10T14:37:26.143 回答
1
    new MutationObserver((mutationsList, observer) => {
        for (var mutation of mutationsList) 
            if (mutation.type === 'childList') 
                Array.from (mutation.addedNodes)
                    .filter (node => node.tagName === 'SCRIPT')
                    .forEach (script => {
                        //Script started loading
                        script.addEventListener ('load', () => { 
                             //Script finished loading
                        })
                    })
    }).observe(document, { attributes: false, childList: true, subtree: true });
于 2021-09-03T09:52:15.700 回答
-2

$.ajax 和 $.load 是一回事。你可以使用任何一个。如果您将 $.load 放在页面上的脚本标记中,它将在加载时触发,就像 $.ajax() 一样。

当谈到在你做某事之前等待脚本触发时,Tomalak 说的是真的。异步调用是个例外。Javascript 将进行 AJAX 调用,然后继续运行脚本,当 AJAX 调用响应时,它将运行成功/失败,具体取决于您告诉它执行的操作。

现在假设您希望您的 JS 等待返回,只需一次调用,只需将所有内容包装在成功回调中即可,或者您可以使用很酷的方式并使用 $.deferred。这允许您进行一堆或一个 ajax 调用,然后仅在完成后运行一些代码。

$.when & $.then 可能最适合这种情况。

无论如何,您正在做的事情都是安全的。

于 2011-09-05T13:47:09.510 回答