动态调用包含document.write的js文件,动态调用外部js文件时,文件中alert起作用 document.write不起作用
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态调用包含document.write的js文件,动态调用外部js文件时,文件中alert起作用 document.write不起作用相关的知识,希望对你有一定的参考价值。
function test()
var script=document.createElement('script');
script.src='js/write.js';
var dd=document.getElementById('dd');
dd.appendChild(script);
通过test函数调用write.js文件 内容主要是document.write('******************'),页面并无内容输出
如果write.js里面是alert内容 则会弹窗!
document.write()方法可以用在两个方面:页面载入过程中用实时脚本创建页面内容,以及用延时脚本创建本窗口或新窗口的内容。该方法需要一个字符串参数,它是写到窗口或框架中的html内容。这些字符串参数可以是变量或值为字符串的表达式,写入的内容常常包括HTML标记语言。
记住,在载入页面后,浏览器输出流自动关闭。在此之后,任何一个对当前页面进行操作的document.write()方法将打开—个新的输出流,它将清除当前页面内容(包括源文档的任何变量或值)。因此,假如希望用脚本生成的HTML替换当前页面,就必须把HTML内容连接起来赋给一个变量,使用一个document.write()方法完成写操作。不必清除文档并打开一个新数据流,一个document.write()调用就可完成所有的操作。
关于document.write()方法还有一点要说明的是它的相关方法document.close()。脚本向窗口(不管是本窗口或其他窗口)写完内容后,必须关闭输出流。在延时脚本的最后一个document.write()方法后面,必须确保含有document.close()方法,不这样做就不能显示图像和表单。并且,任何后面调用的document.write()方法只会把内容追加到页面后,而不会清除现有内容来写入新值。
现在是页面已经加载进来了,所以我认为点击后,加载进来的js,执行document.write,那么文本的输出浏览器不处理,而不是像加载时输出在当前元素里面。
那个write.js可以这样改:
var dd=document.getElementById(\'dd\');
dd.innerHTML = dd.innerHTML + \'******************\';
alert(\'ccc\');
test2(); 参考技术A 原来 document.write(‘XX’)还有这么多说法,原来一直以为它与document.body.innerHTML = 'XX';等效呢!
6rl网友的引用分析应该是正确的。
使用可能包含 document.write 的 src 动态添加脚本标签
【中文标题】使用可能包含 document.write 的 src 动态添加脚本标签【英文标题】:Dynamically add script tag with src that may include document.write 【发布时间】:2022-01-06 15:36:21 【问题描述】:我想在网页中动态包含一个脚本标签,但是我无法控制它的 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
?
jsfiddle of what i've tried
【问题讨论】:
经过数小时苦苦挣扎的 postscribe 是解决方案! https://github.com/krux/postscribe/ async loading javascript with document.write的可能重复 【参考方案1】:var my_awesome_script = document.createElement('script');
my_awesome_script.setAttribute('src','http://example.com/site.js');
document.head.appendChild(my_awesome_script);
【讨论】:
【参考方案2】:您可以像这样使用document.createElement()
函数:
function addScript( src )
var s = document.createElement( 'script' );
s.setAttribute( 'src', src );
document.body.appendChild( s );
【讨论】:
你如何使这个异步? @mobile 家伙:s.async = true; s.setAttribute('src', src);可能是 s.src = src(我认为?)我知道这不是 pcg【参考方案3】:有onload
函数,脚本加载成功后可以调用:
function addScript( src, callback )
var s = document.createElement( 'script' );
s.setAttribute( 'src', src );
s.onload=callback;
document.body.appendChild( s );
【讨论】:
学到了一些新东西。不错!【参考方案4】:我为加载多个脚本而编写的一个不错的小脚本:
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
);
【讨论】:
对不起...刚刚找到一个更好的允许依赖***.com/a/1867135/678780【参考方案5】:这样做的唯一方法是将document.write
替换为您自己的函数,该函数会将元素附加到页面底部。使用 jQuery 非常简单:
document.write = function(htmlToWrite)
$(htmlToWrite).appendTo('body');
如果您有 html 像问题示例一样以块的形式进入 document.write,您需要缓冲 htmlToWrite
段。也许是这样的:
document.write = (function()
var buffer = "";
var timer;
return function(htmlPieceToWrite)
buffer += htmlPieceToWrite;
clearTimeout(timer);
timer = setTimeout(function()
$(buffer).appendTo('body');
buffer = "";
, 0)
)()
【讨论】:
【参考方案6】:你可以试试下面的代码sn-p。
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());
【讨论】:
【参考方案7】:嗯,有多种方法可以包含动态 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 文件。这里有一个完整的教程。
Inserting Dynamic Javascript the right way
【讨论】:
fyi,链接失效,我在别处找不到这篇文章。【参考方案8】:我尝试了递归地附加每个脚本
注意如果您的脚本一个接一个地依赖,那么位置将需要同步。
主要依赖项应该在数组的最后,以便初始脚本可以使用它
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])
【讨论】:
【参考方案9】:这是一个缩小的 sn-p,与 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
替换为您的脚本路径。
【讨论】:
【参考方案10】:这是为我工作的。
你可以检查一下。
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");
【讨论】:
【参考方案11】:当脚本被异步加载时,它们不能调用 document.write。这些调用将被忽略,并且将向控制台写入警告。
您可以使用以下代码动态加载脚本:
var scriptElm = document.createElement('script');
scriptElm.src = 'source.js';
document.body.appendChild(scriptElm);
仅当您的源属于单独的文件时,此方法才有效。
但是如果你有源代码作为你想要动态加载的内联函数并且想要将其他属性添加到脚本标签,例如类,类型等,那么下面的 sn-p 会帮助你:
var scriptElm = document.createElement('script');
scriptElm.setAttribute('class', 'class-name');
var inlineCode = document.createTextNode('alert("hello world")');
scriptElm.appendChild(inlineCode);
document.body.appendChild(scriptElm);
【讨论】:
target
是什么?
@Gel,更新了答案,大多数情况下目标是document.body
。【参考方案12】:
单行(不过与上述答案没有本质区别):
document.body.appendChild(document.createElement('script')).src = 'source.js';
【讨论】:
【参考方案13】:以正确的顺序加载相互依赖的脚本。
基于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])
【讨论】:
【参考方案14】:没有人提到它,但您也可以使用URL
和Blob
将实际源代码制作成一个URL,将其粘贴到脚本标签中:
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)
【讨论】:
【参考方案15】:window.addEventListener("load", init);
const loadScript = async (url) =>
const response = await fetch(url);
const script = await response.text();
eval(script);
function init()
const wistiaVideo = document.querySelector(".wistia_embed");
if ("IntersectionObserver" in window && "IntersectionObserverEntry" in window && "intersectionRatio" in window.IntersectionObserverEntry.prototype)
let lazyVideoObserver = new IntersectionObserver(function (entries, observer)
entries.forEach(function (entry)
if (entry.isIntersecting)
setTimeout(() => loadScript("//fast.wistia.com/assets/external/E-v1.js"), 1000);
lazyVideoObserver.unobserve(entry.target);
console.log("E-v1.js script loaded from fast.wistia.com");
);
);
lazyVideoObserver.observe(wistiaVideo);
<div style="height: 150vh; background-color: #f7f7f7;"></div>
<h1>Wistia Video!</h1>
<div class="wistia_embed wistia_async_29b0fbf547" style="width:640px;height:360px;"> </div>
<h1>Video Ended!</h1>
【讨论】:
正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center。【参考方案16】:差不多十年过去了,没有人费心写Promise
版本,所以这是我的(基于this 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的js文件,动态调用外部js文件时,文件中alert起作用 document.write不起作用的主要内容,如果未能解决你的问题,请参考以下文章