我有2个文件,第一个文件有一些HTML和JS的一部分。第二个文件是主文件,它通过XmlHttpRequest加载第一个文件。
第一个文件是这样的:
<div>
My HTML contents
</div>
<script id="my_js_block">
function my_function() {
alert(9);
}
</script>
第二个文件是这样的:
<div id="div_ajax_content">
</div>
<script>
function load_ajax_content() {
//synchronously with XmlHttpRequest(...,...,false);
//...load and throw the first file into 'div_ajax_content'
}
load_ajax_content();
my_function(); <-- fails here
</script>
如何解决这个问题?
Ajax是异步的。您的代码试图在XMLHttpRequest
完成之前调用my_function()
。这样做:
<script>
function load_ajax_content() {
//...load and throw the first file into 'div_ajax_content'
// then,
my_function();
}
load_ajax_content();
</script>
现在ajax调用是同步的。您可以为<script>
标签解析返回的HTML,并单独处理它们,但这并不漂亮:
function load_ajax_content() {
//...load and throw the first file into 'div_ajax_content'
// then grab the script nodes one-by-one
var scriptElts = document.getElementById('div_ajax_content').getElementsByTagName('script'),
scriptElt,
propName; // http://www.quirksmode.org/dom/w3c_html.html#t07
if (scriptElts.length) {
propName = scriptElts[0].textContent ? 'textContent' : 'innerText';
}
for (var i=0; i<scriptElts.length; i++) {
scriptElt = document.createElement('script');
scriptElt[propName] = scriptElts[i][propName];
document.body.appendChild(scriptElt);
}
// finally,
my_function();
}
…或者您可以使用像jQuery这样的库,它可以自动为您处理这个问题(以及许多其他问题!)。
通过innerHTML添加脚本不会运行脚本。因此,您的函数没有被定义,因此失败。
相反,我建议分别加载HTML和JS,并使用DOM方法添加JS以将<script>
标记放在页面上,或eval()
执行返回的文件内容。
我发现了一个非常有趣的方法,但它的工作!
load_ajax_contents();
eval(document.getElementById("my_js_block").innerHTML);
my_function();
然而,为了使这些函数的eval() 求值为全局,必须将第一个文件中的所有函数声明为变量,如下所示:
//this works!
my_function = function() {
alert(9);
}
而不是:
//this makes the function nested in the context where eval() is called
function my_function() {
alert(9);
}
和not:
//this makes the variable local to the context where eval() is called
var my_function = function() {
alert(9);
}