如何将DOM元素脚本添加到head部分?

46

我想在HTML的头部添加DOM元素。jQuery不允许向头部添加DOM元素脚本,它们会被执行,参考链接

我想在<head>部分添加script标签,并编写一个脚本。

var script = '<script type="text/javascript"> //function </script>'
$('head').append(script);

我想在函数中实现以下功能。我尝试使用jQuery和javascript,但都没有成功。

请告诉我如何通过jQuery或javascript将脚本添加并写入标签中。

我尝试使用javascript添加DOM元素,但使用.innerHTML()写入标签时无法正常工作。我正在使用jQuery 2.0.3和jQuery UI 1.10.3。

我想将base64编码的脚本添加到标签中。我使用类似这样的base64解码器js来解码javascript代码,然后将其放在部分。

//编辑过的
最终结果为:

$.getScript('base64.js');
var encoded = "YWxlcnQoImhpIik7DQo="; //More text
var decoded = decodeString(encoded);
var script = '<script type="text/javascript">' +decoded + '</script>';
$('head').append(script);
为了将编码脚本和附加项合并到一个JavaScript文件中,我想使用 base64.js 或其他一些解码器 JavaScript 文件,因为某些浏览器不支持 atob()

1
你尝试过使用$.getScript()吗? - Jai
我想将<script>//function<\script>添加到文档的头部。 - john3825
动态添加DOM元素会导致不稳定,因为它们依赖于浏览器,即使使用.readyState()检查状态也无法解决。也许EventListner可以解决问题,但是由于动态加载的趋势,所有这些方法都不太好,参考链接 - john3825
使用Data Url直接查看我的答案,避免下载base64.js的需要 - newScript.src =“data:text/plain;base64,YWxlcnQoImhpIik7DQo =” - Jerome WAGNER
13个回答

91

请尝试这个

var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'url';    

document.head.appendChild(script);

6
我想在头部添加一个脚本,而不是整个脚本文件。 - john3825
34
document.head 相对于 document.getElementsByTagName('head')[0] 更好。 - Franklin Yu
这很棒,简单而又引人入胜。 - Faris Rayhan

18
如果在头部注入多个包含本地和远程脚本文件的脚本标签,可能会出现这样的情况:依赖外部脚本(如从 googleapis 加载 jQuery)的本地脚本将出现错误,因为本地脚本可能在外部脚本加载之前被加载,导致类似这样的问题:(jquery.some-plugin.js 中出现“jQuery 未定义”的错误)。
var head = document.getElementsByTagName('head')[0];

var script = document.createElement('script');
script.type = 'text/javascript';
script.src = "https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js";
head.appendChild(script);

var script = document.createElement('script');
script.type = 'text/javascript';
script.src = "/jquery.some-plugin.js";
head.appendChild(script);
当然,这种情况就是 .onload() 的作用所在,但如果要加载多个脚本,这可能会很麻烦。 为了解决这个问题,我编写了这个函数,它将保持一个要加载的脚本队列,在前一个脚本完成后加载每个后续项目,并返回一个 Promise,该 Promise 在脚本(或队列中的最后一个脚本,如果没有参数)加载完成时解析。
load_script = function(src) {
    // Initialize scripts queue
    if( load_script.scripts === undefined ) {
        load_script.scripts = [];
        load_script.index = -1;
        load_script.loading = false;
        load_script.next = function() {
            if( load_script.loading ) return;

            // Load the next queue item
            load_script.loading = true;
            var item = load_script.scripts[++load_script.index];
            var head = document.getElementsByTagName('head')[0];
            var script = document.createElement('script');
            script.type = 'text/javascript';
            script.src = item.src;
            // When complete, start next item in queue and resolve this item's promise
            script.onload = () => {
                load_script.loading = false;
                if( load_script.index < load_script.scripts.length - 1 ) load_script.next();
                item.resolve();
            };
            head.appendChild(script);
        };
    };

    // Adding a script to the queue
    if( src ) {
        // Check if already added
        for(var i=0; i < load_script.scripts.length; i++) {
            if( load_script.scripts[i].src == src ) return load_script.scripts[i].promise;
        }
        // Add to the queue
        var item = { src: src };
        item.promise = new Promise(resolve => {item.resolve = resolve;});
        load_script.scripts.push(item);
        load_script.next();
    }

    // Return the promise of the last queue item
    return load_script.scripts[ load_script.scripts.length - 1 ].promise;
};

通过添加脚本来确保在开始下一个脚本之前完成先前的脚本,可以像这样完成...

["https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js",
 "/jquery.some-plugin.js",
 "/dependant-on-plugin.js",
].forEach(load_script);

或者加载脚本并使用返回的Promise,在其完成时执行工作...

load_script("some-script.js")
.then(function() {
    /* some-script.js is done loading */
});

这是一个非常出色且完整的解决方案,我非常感谢您的分享。我将它用作轻量级库的一部分,在Notepad++中执行JavaScript代码。 - Chris
我认为这是一个超级解决方案,应该被接受作为答案。 - lehel
使用原生JS是一个很好的解决方案,它不仅节省时间,而且比编写和解析冗余的HTML脚本标签更加简洁。 - R. StackUser
这是一篇关于加载脚本的好文章:https://www.html5rocks.com/en/tutorials/speed/script-loading/ - JoAMoS

12

try out ::

var script = document.createElement("script");
script.type="text/javascript";
script.innerHTML="alert('Hi!');";
document.getElementsByTagName('head')[0].appendChild(script);


8

根据作者所说,他们想要在头部创建一个脚本,而不是链接到脚本文件。此外,为了避免 jQuery(在这种情况下提供的有用功能很少)带来的复杂性,使用原生 JavaScript 可能更好。

可以像这样实现:

var script = document.createTextNode("<script>alert('Hi!');</script>");   
document.getElementsByTagName('head')[0].appendChild(script);

一些可能对此感到困惑的人的澄清: 网页中的所有代码都是文本。文本是网页中最基本的类型。浏览器只需按照其规则逐步处理文本,直到达到结尾(包括回路、递归等)。 为使其起作用,创建此标签的脚本必须在标头中。浏览器在处理时将在到达标头的结尾之前先遇到此代码,将所需的脚本附加到标头中,随后继续处理并最终到达它。如果您有一个可靠的页脚结尾,您可以将“head”更改为“footer”或类似的内容,但考虑到大多数具有脚本的站点上存在标头标签是最可靠的,因此在此情况下它是最有用的选项。

createTextNode?!那只会将您的文本添加到头部,而不会创建脚本标签。 - Gyuri
脚本就是文本。请注意我的示例中的起始标签“<script>”和结束标签“</script>”。 - lilHar
这个只是将文本添加到头部,而不是脚本标签。 - Long Nguyen
@LongNguyen 我只能假设当你测试它时,你用你想要的任何东西替换了"<script>alert('Hi!');</script>"。不要这样做。仅用你想要的脚本替换alert('Hi!');,或者你在body中运行脚本。问题是,整个网站“仅仅”是文本。脚本标签就是文本。如果这在浏览器完成头部处理之前运行,警报触发。如果你只是想让一个脚本存在以便稍后调用,那么它会起作用。 - lilHar
@lilHar 不,我保留了你写的所有内容,没有替换任何东西。 - Long Nguyen
奇怪,这在我这里可以运行。你把它放在哪里了?记住保持运行顺序很重要。 - lilHar

5

我找到的最佳解决方案:

AppendToHead('script', 'alert("hii"); ');
//or
AppendToHead('script', 'http://example.com/script.js');
//or
AppendToHead('style', '#myDiv{color:red;} ');
//or
AppendToHead('style', 'http://example.com/style.css');

function AppendToHead(elemntType, content) {
  // detect whether provided content is "link" (instead of inline codes)
  var Is_Link = content.split(/\r\n|\r|\n/).length <= 1 && content.indexOf("//") > -1 && content.indexOf(" ") <= -1;
  if (Is_Link) {
    if (elemntType == 'script') {
      var x = document.createElement('script');
      x.id = id;
      x.src = content;
      x.type = 'text/javascript';
    } else if (elemntType == 'style') {
      var x = document.createElement('link');
      x.id = id;
      x.href = content;
      x.type = 'text/css';
      x.rel = 'stylesheet';
    }
  } else {
    var x = document.createElement(elemntType);
    if (elemntType == 'script') {
      x.type = 'text/javascript';
      x.innerHTML = content;
    } else if (elemntType == 'style') {
      x.type = 'text/css';
      if (x.styleSheet) {
        x.styleSheet.cssText = content;
      } else {
        x.appendChild(document.createTextNode(content));
      }
    }
  }
  //append in head
  (document.head || document.getElementsByTagName('head')[0]).appendChild(x);
}

3
var script = $('<script type="text/javascript">// function </script>')
document.getElementsByTagName("head")[0].appendChild(script[0])

但在这种情况下,脚本将不会被执行,并且函数将无法在全局命名空间中访问。 要在 <script> 中使用代码,您需要按照问题中的方式进行操作。 $('head').append(script);

这个答案出乎意料地帮了我。第三方脚本通过查找<script>标签本身来检查我的添加脚本的存在,所以我不得不使用这种方法来“欺骗”它。 - Eric N

2
这是一个老问题,我知道它特别询问如何将脚本标签添加到头部,但是根据OP的解释,他们实际上只是想执行通过其他JS函数获取的一些JS代码。
这比在页面中添加脚本标签要简单得多。
只需:
eval(decoded);

EVAL函数可以直接执行一段JS代码,不需要将其添加到DOM中。

我认为在页面加载后没有必要将内联脚本标签添加到DOM中。

更多信息请参见:http://www.w3schools.com/jsref/jsref_eval.asp


2
如果您想添加带有一些脚本的脚本标签,请使用:

如果您想添加带有一些脚本的脚本标签,请使用:

var script= document.createElement('script');
script.text = "alert('Hi!');";
document.head.appendChild(script);

1
您可以直接使用"Data URL"。以您的示例中的数据为例:
var newScript = document.createElement("script");
newScript.type = "text/javascript";
document.head.appendChild(newScript);
newScript.src = "data:text/plain;base64,YWxlcnQoImhpIik7DQo="

这样,您可以跳过加载base64.js并直接评估base64编码的脚本。


1
<script type="text/JavaScript">
     var script = document.createElement('SCRIPT');
    script.src = 'YOURJAVASCRIPTURL';
    document.getElementsByTagName('HEAD')[0].appendChild(script);
 </script>

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