我想在网页中动态地包括一个脚本标签,但我无法控制它的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>

在头部工作很好,但有没有其他方法,我可以动态添加source.js使用innerHTML之类的东西?

我已经试过了


当前回答

以下是一个简化的代码片段,与谷歌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替换为脚本路径。

其他回答

这是我的工作。

你可以检查一下。

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); 窗口。Onload = function() { if (window.jQuery) { //加载jQuery 警报(“在头部添加脚本标签!”); }其他{ //不加载jQuery 警告(“没有在头部添加脚本标签”); } }

以下是一个简化的代码片段,与谷歌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替换为脚本路径。

没有人提到它,但你也可以通过使用URL和Blob将实际的源代码插入到脚本标记中:

const jsCode = `
 // JS code in here. Maybe you extracted it from some HTML string.
`

const url = URL.createObjectURL(new Blob([jsCode]))
const script = document.createElement('script')
script.src = url
URL.revokeObjectURL(url) // dispose of it when done

至于jsCode,你可能已经从一些HTML中得到了它。

这里有一个更完整的例子,你如何处理HTML源代码中的任意数量的脚本:

main()

async function main() {
    const scriptTagOpen = /<script\b[^>]*>/g
    const scriptTagClose = /<\/script\b[^>]*>/g
    const scriptTagRegex = /<script\b[^>]*>[\s\S]*?<\/script\b[^>]*>/g

    const response = await fetch('path/to/some.html')
    const html = await response.text()

    someElement.innerHTML = html

    // We need to get the script tags and manually add them to DOM
    // because otherwise innerHTML will not execute them.
    const codes =
        html
            .match(scriptTagRegex)
            ?.map(code => code.replace(scriptTagOpen, '').replace(scriptTagClose, ''))
            .map(code => URL.createObjectURL(new Blob([code]))) || []

    for (const code of codes) {
        const script = document.createElement('script')
        script.src = code
        someElement.append(script)
        URL.revokeObjectURL(code)
    }
}
var my_awesome_script = document.createElement('script');

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

document.head.appendChild(my_awesome_script);

我写了一个漂亮的小脚本来加载多个脚本:

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
});