我正在动态创建脚本标记:
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.charset = 'utf-8';
script.defer = true;
script.async = true;
script.text = 'some my javascript content here';
head.appendChild(script);
script.onload = function () {
// this never get fired..
debugger;
}
如何在其他代码块中执行脚本时收到通知?也许有些事情?
谢谢!
答案 0 :(得分:9)
我能够通过向脚本添加ID来实现此功能,然后在JS中,手动触发该DOM元素上的load事件。仅在Chrome中进行测试,根据MDN)在旧IE中会出现问题。
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.charset = 'utf-8';
script.id = 'testing';
script.defer = true;
script.async = true;
script.onload = function () {
console.log('The script is loaded');
}
script.text = ["console.log('This is from the script');",
"var script = document.getElementById('testing');",
"var event = new UIEvent('load');",
"script.dispatchEvent(event);"].join('');
head.appendChild(script);
答案 1 :(得分:1)
在现代浏览器中,您可以使用Mutation Observer来检测元素中的更改 - 在这种情况下为head
。像这样:
observer = new MutationObserver(function (m) {
// This will be fired
});
observer.observe(document.head, {childList: true});
不幸的是,这在IE< 11,但似乎在IE中触发onload
,因此您可以将其用于IE。
答案 2 :(得分:0)
如果脚本被附加到DOM,则代码每100毫秒检查一次。您可以在应用程序中的任何位置使用它,而无需事件侦听器和调度事件。 同样,您可以看到一个时间间隔,如果脚本没有在您设置的时间间隔内追加,代码将在该时间间隔内抛出错误。
const waitForScriptToLoad = (scriptName, checkTimeMs, timeOutMs) => {
let elapsedTime = 0;
return new Promise((resolve, reject) => {
setTimeout(x => reject('script: ' + scriptName + ' Timed out!')
, timeOutMs)
const time = setInterval(() => {
elapsedTime += checkTimeMs;
if (document.body.innerHTML.indexOf(scriptName) > -1) {
resolve(
{
response: 'script: ' + scriptName + ' found!',
time: (elapsedTime / 1000).toFixed(2) + 's'
});
clearInterval(time);
}
}, checkTimeMs)
})
}
waitForScriptToLoad('script_name.js', 100, 20000)
.then(res => console.log(res))
.catch(err => console.log(err))
答案 3 :(得分:-1)
在设置脚本源之前,需要定义onload
函数。但是,正如Teemu告诉我的那样,由于您是通过text
属性编写javascript,因此onload
事件永远不会触发。您最好的选择是拥有一个外部js文件并通过src
属性加载它。
订单应该是:
- 将脚本元素附加到DOM
- 定义onload函数
- 定义
src
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.charset = 'utf-8';
script.defer = true;
script.async = true;
head.appendChild(script);
script.onload = function () {
// this never get fired..
debugger;
}
script.src = 'scriptName.js';
然后你的onload事件应该触发,你可以在函数中插入console.log("script has loaded!");
语句。
答案 4 :(得分:-1)
将代码解压缩到.js文件。
将script.src = 'yourjs.js';
添加到脚本中。
将脚本添加到DOM时,会立即执行.js文件。
在if(console){console.debug('helloworld.');}
的ontop上添加yourjs.js
,您会看到该消息。
答案 5 :(得分:-1)
另一种解决方案(不使用onload
或src
)
window.onload = function(){
var script = document.createElement('SCRIPT'),
content = 'console.debug("Hello Kitty");'; // or console.log
script.type = 'text/javascript';
try {
script.appendChild(document.createTextNode(content));
} catch (e) {
script.text = content;
} finally {
document.getElementsByTagName("HEAD")[0].appendChild(script);
}
};
Working demo(在IE,FF,Chrome和Opera上测试过)
答案 6 :(得分:-2)
出于测试目的,您始终可以添加对alert()函数的调用。但是,在查看您的代码后,我不确定我是否在其中看到实际调用该函数的任何内容。那" onload"在执行appendChild()之前,可能应该将事件处理程序添加到动态创建部分。
我一段时间写了一些代码来做一些动态脚本创建,它运行正常。我的代码有两个主要功能,一个用于创建脚本(一堆脚本),从" .js"中加载数据。文件和另一个调用这些脚本中的函数的顺序,由它们的名称决定(使用" eval()"函数)。你的函数没有我能看到的任何名字......我知道很多人都不喜欢使用eval()函数,但只要它被调用的唯一东西就是你在其中写的东西整个,应该没事。
此代码允许BROWSER而不是Web服务器动态创建可点击链接项的菜单(每个可点击链接看起来像普通超链接,但实际上是JavaScript构造,浏览器必须为其启用JavaScript链接工作 - 但它必须启用JavaScript才能创建菜单,所以没问题!):
var F00, F01, F02, F03, F04, F05, F06, F07, F08, F09,
F10, F11, F12, F13, F14, F15, F16, F17, F18, F19;
var dat = new Array();
var form, script, str, st2, tmp, tmp2, dtno, indx, unde;
function initialize()
{ window.name="MyMenu";
form = document.getElementById('MENU');
for(indx=0; indx<20; indx++)
{ str = "0" + indx;
tmp = str.length - 2;
str = str.substr(tmp);
script = document.createElement('script');
script.type = 'text/javascript';
script.src = str + ".js";
form.appendChild(script);
}
window.setTimeout("BuildMenu();", 1000); //delay is necessary;
// scripts are actually only loaded after the function ends,
// and you need to allow time for it to finish
// before calling the functions in those scripts.
return;
}
请注意,此代码已准备好处理20个菜单项,即使您目前只有5个项目可以在菜单上使用。如果20个最大值中的一些&#34; .js&#34;以上功能不会崩溃。文件不存在。
function BuildMenu()
{ dtno = 0;
for(indx=0; indx<20; indx++)
{ str = "0" + indx;
tmp = str.length - 2;
str = "F" + str.substr(tmp);
tmp = eval(str);
if(tmp != unde) //no value is assigned to 'unde'; it is undefined;
//this is a valid way to find out
//whether or not a ".js" script existed/was-loaded.
dat[dtno++] = eval(str + "()");
}
dat.sort();
for(indx=0; indx<dtno; indx++)
{ str = "0" + indx;
tmp = str.length - 2;
str = "W" + str.substr(tmp);
tmp = document.getElementById(str);
tmp.innerHTML = "<a onclick=\"window.open('" + dat[indx][1] + "', 'MyMenu');\" style=\"color:#0000ff;text-decoration:underline;cursor:pointer;\">" + dat[indx][0] + "</a> " + dat[indx][2] + "<br />";
}
return;
}
在网页的HTML代码中,有以下内容:
<body onload="initialize();>
<br />
<form id="MENU" action="" onsubmit="return false;">
<span id="W00"> </span>
<span id="W01"> </span>
<span id="W02"> </span>
<span id="W03"> </span>
<span id="W04"> </span>
<span id="W05"> </span>
<span id="W06"> </span>
<span id="W07"> </span>
<span id="W08"> </span>
<span id="W09"> </span>
<span id="W10"> </span>
<span id="W11"> </span>
<span id="W12"> </span>
<span id="W13"> </span>
<span id="W14"> </span>
<span id="W15"> </span>
<span id="W16"> </span>
<span id="W17"> </span>
<span id="W18"> </span>
<span id="W19"> </span>
</form>
以下是&#34; 00.js&#34;的一些示例代码。文件:
<!--
function F00()
{ return ["Menu Item Alpha", "./Alpha.htm", "Select Web Page Alpha"];
}
-->
注意该函数只返回3个数组元素(字符串)。 BuildMenu()函数在构建网页上的菜单时使用这些字符串,部分是通过修改span元素的innerHTML。