使用src动态添加脚本标签,其中可能包含document.write


160

我想在网页中动态添加脚本标签,但是我无法控制它的src,因此src =“ source.js”可能看起来像这样。

document.write('<script type="text/javascript">')
document.write('alert("hello world")')
document.write('</script>')
document.write('<p>goodbye world</p>')

现在通常

<script type="text/javascript" src="source.js"></script> 

在头上工作正常,但还有其他方法可以使用诸如innerHTML之类的方法动态添加source.js吗?

我尝试过的


2
经过数小时的苦苦挣扎才是解决方案!https://github.com/krux/postscribe/
Cadell Christo 2012年

Answers:


210
var my_awesome_script = document.createElement('script');

my_awesome_script.setAttribute('src','http://example.com/site.js');

document.head.appendChild(my_awesome_script);

94

您可以使用如下document.createElement()功能:

function addScript( src ) {
  var s = document.createElement( 'script' );
  s.setAttribute( 'src', src );
  document.body.appendChild( s );
}

您如何使这个异步?
UKDataGeek '16

3
@mobile bloke:s.async = true;
axlotl

s.setAttribute('src',src); 可能是s.src = src(我认为吗?)我知道这不是pcg
Brandito

67

有一个onload函数,脚本成功加载后可以调用:

function addScript( src,callback) {
  var s = document.createElement( 'script' );
  s.setAttribute( 'src', src );
  s.onload=callback;
  document.body.appendChild( s );
}

学到了新东西。真好!
mix3d

16

我写的一个不错的小脚本来加载多个脚本:

function scriptLoader(scripts, callback) {

    var count = scripts.length;

    function urlCallback(url) {
        return function () {
            console.log(url + ' was loaded (' + --count + ' more scripts remaining).');
            if (count < 1) {
                callback();
            }
        };
    }

    function loadScript(url) {
        var s = document.createElement('script');
        s.setAttribute('src', url);
        s.onload = urlCallback(url);
        document.head.appendChild(s);
    }

    for (var script of scripts) {
        loadScript(script);
    }
};

用法:

scriptLoader(['a.js','b.js'], function() {
    // use code from a.js or b.js
});

2
抱歉...刚刚找到了一个更好的允许依赖的方法stackoverflow.com/a/1867135/678780
EliSherer

5

您可以尝试以下代码段。

function addScript(attribute, text, callback) {
    var s = document.createElement('script');
    for (var attr in attribute) {
        s.setAttribute(attr, attribute[attr] ? attribute[attr] : null)
    }
    s.innerHTML = text;
    s.onload = callback;
    document.body.appendChild(s);
}

addScript({
    src: 'https://www.google.com',
    type: 'text/javascript',
    async: null
}, '<div>innerHTML</div>', function(){});

4

这是我的工作。

您可以检查一下。

var script_tag = document.createElement('script');
script_tag.setAttribute('src','https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js');
document.head.appendChild(script_tag);
window.onload = function() {
    if (window.jQuery) {  
        // jQuery is loaded  
        alert("ADD SCRIPT TAG ON HEAD!");
    } else {
        // jQuery is not loaded
        alert("DOESN'T ADD SCRIPT TAG ON HEAD");
    }
}


3

异步加载脚本时,它们无法调用document.write。这些调用将被简单地忽略,并且警告将被写入控制台。

您可以使用以下代码动态加载脚本:

var scriptElm = document.createElement('script');
scriptElm.src = 'source.js';
document.body.appendChild(scriptElm);

仅当您的源文件属于单独的文件时,此方法才有效。

但是,如果您有源代码作为内联函数,并且要动态加载并希望向脚本标记添加其他属性,例如类,类型等,那么以下代码片段将为您提供帮助:

var scriptElm = document.createElement('script');
scriptElm.setAttribute('class', 'class-name');
var inlineCode = document.createTextNode('alert("hello world")');
scriptElm.appendChild(inlineCode); 
target.appendChild(scriptElm);

2

好吧,有多种方法可以包含动态javascript,我在许多项目中都使用了这一方法。

var script = document.createElement("script")
script.type = "text/javascript";
//Chrome,Firefox, Opera, Safari 3+
script.onload = function(){
console.log("Script is loaded");
};
script.src = "file1.js";
document.getElementsByTagName("head")[0].appendChild(script);

您可以调用create通用函数,该函数可以帮助您根据需要加载尽可能多的javascript文件。这里有一个完整的教程。

正确插入动态Javascript


2
仅供参考,链接无效,我在其他地方找不到该文章。
user1063287

1

唯一的方法是document.write用您自己的函数替换,该函数会将元素追加到页面底部。jQuery非常简单:

document.write = function(htmlToWrite) {
  $(htmlToWrite).appendTo('body');
}

如果您像问题示例那样以大块的形式进入document.write的html,则需要缓冲这些htmlToWrite段。也许是这样的:

document.write = (function() {
  var buffer = "";
  var timer;
  return function(htmlPieceToWrite) {
    buffer += htmlPieceToWrite;
    clearTimeout(timer);
    timer = setTimeout(function() {
      $(buffer).appendTo('body');
      buffer = "";
    }, 0)
  }
})()

1

我通过递归附加每个脚本来尝试

注意如果脚本相互依存,则位置需要同步。

主要依赖关系应位于数组的最后,以便初始脚本可以使用它

const scripts = ['https://www.gstatic.com/firebasejs/6.2.0/firebase-storage.js', 'https://www.gstatic.com/firebasejs/6.2.0/firebase-firestore.js', 'https://www.gstatic.com/firebasejs/6.2.0/firebase-app.js']
let count = 0

  
 const recursivelyAddScript = (script, cb) => {
  const el = document.createElement('script')
  el.src = script
  if(count < scripts.length) {
    count ++
    el.onload = recursivelyAddScript(scripts[count])
    document.body.appendChild(el)
  } else {
    console.log('All script loaded')
    return
  }
}
 
  recursivelyAddScript(scripts[count])


1

以正确的顺序加载相互依赖的脚本。

基于Satyam Pathak的响应,但修复了onload。它是在脚本实际加载之前触发的。

const scripts = ['https://www.gstatic.com/firebasejs/6.2.0/firebase-storage.js', 'https://www.gstatic.com/firebasejs/6.2.0/firebase-firestore.js', 'https://www.gstatic.com/firebasejs/6.2.0/firebase-app.js']
let count = 0

  
 const recursivelyAddScript = (script, cb) => {
  const el = document.createElement('script')
  el.src = script
  if(count < scripts.length) {
    count ++
    el.onload = () => recursivelyAddScript(scripts[count])
    document.body.appendChild(el)
  } else {
    console.log('All script loaded')
    return
  }
}
 
  recursivelyAddScript(scripts[count])


0

这是一个简短的代码段,与Google Analytics(分析)和Facebook Pixel使用的代码相同:

!function(e,s,t){(t=e.createElement(s)).async=!0,t.src="https://example.com/foo.js",(e=e.getElementsByTagName(s)[0]).parentNode.insertBefore(t,e)}(document,"script");

https://example.com/foo.js用您的脚本路径替换。


0

单线(尽管与上面的答案没有本质区别):

document.body.appendChild(document.createElement('script')).src = 'source.js';
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.