我想在网页中动态地包括一个脚本标签,但我无法控制它的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替换为脚本路径。
没有人提到它,但你也可以通过使用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)
}
}
差不多十年过去了,没有人愿意写Promise的版本,所以这里是我的版本(基于这个awnser):
function addScript(src) {
return new Promise((resolve, reject) => {
const s = document.createElement('script');
s.setAttribute('src', src);
s.addEventListener('load', resolve);
s.addEventListener('error', reject);
document.body.appendChild(s);
});
}
使用
try {
await addScript('https://api.stackexchange.com/js/2.0/all.js');
// do something after it was loaded
} catch (e) {
console.log(e);
}
当脚本异步加载时,它们不能调用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);
document.body.appendChild(scriptElm);