ksn*_*sno 12 html javascript dom
所以这就是我们的场景......我们首先要做的是,我们附加一段javascript代码,将外部脚本添加到文档中,如下所示:
(function() {
var e = document.createElement('script'); e.type = 'text/javascript'; e.async = true; e.src = 'http://blabla.com/script.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(e, s);
})();
Run Code Online (Sandbox Code Playgroud)
然后script.js发生以下情况:
function ajaxCall() {
//... some script to send ajax request which calls createDiv() after success
if (window.XMLHttpRequest){
xmlhttp=new XMLHttpRequest();
}
else{
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function(){
if(xmlhttp.readyState==4&&xmlhttp.status==200){
createDiv(xmlhttp.responseText);
}
};
xmlhttp.open("GET","http://blabla.com/api/");
xmlhttp.send();
}
function parseResponse(response) {
var parser = new DOMParser();
var dom = parser.parseFromString(response, "text/html");
return dom;
}
function createDiv(responsetext)
{
var dom = parseResponse(responsetext);
var _ws = dom.getElementById('styles');
var h = document.getElementsByTagName('head')[0];
h.appendChild(document.importNode(_ws, true));
var _jr = dom.getElementById('script1').outerHTML;
var _vc = dom.getElementById('script2').outerHTML;
var _rv = dom.getElementById('script3').outerHTML;
var _rw = dom.getElementById('my_div');
var _b = document.getElementsByTagName('body')[0];
var _d = document.createElement('div'); _d.id = 'just_id';
_d.innerHTML = _jr + _vc + _rv;
_d.appendChild(document.importNode(_rw, true));
_b.appendChild(_d);
}
ajaxCall();
Run Code Online (Sandbox Code Playgroud)
一切正常,脚本和div按预期和预期的方式被追加,但附加的脚本不会被执行,也不会影响附加的div.这是为什么?我怎样才能让它执行?我们也没有在控制台中收到任何警告/错误.使用最新的Firefox.
编辑1
注释:您展示的示例脚本只定义了函数,但它实际上从未调用它们
它实际上调用了一个发出ajax请求的函数,请检查编辑过的代码片段.
编辑2
评论:您是否尝试将逻辑放入回调中,然后在createDiv中调用它?可能会添加一些日志来测试它是否被调用但无法找到div
我只是尝试console.log('hello world');调用其中一个脚本,这些脚本被createDiv()函数追加,但它什么也没做.
编辑3
更多细节.当页面加载时,我可以看到
<script type="text/javascript" id="script1" src="http://blabla.com/script1.js"></script>
<script type="text/javascript" id="script2" src="http://blabla.com/script2.js"></script>
<script type="text/javascript" id="script3" src="http://blabla.com/script3.js"></script>
<div id="just_id">Content here</div>
Run Code Online (Sandbox Code Playgroud)
在DOM-Inspector中,如上所述,有console.log('hello world');测试它,但它没有被执行.
编辑4
通过createDiv()函数为文档添加了一些CSS <head></head>,它会影响我的id为'just_id'的div.JS仍然无法正常工作.
编辑5
还尝试在我的函数中添加内联javascript而不是外部javascript,但仍然没有成功.可以在DOM-Inspector中看到以下内容,但代码不会记录任何内容.
<script type="text/javascript">
console.log('test');
</script>
Run Code Online (Sandbox Code Playgroud)
编辑6
我也尝试从这里建议导入节点
不允许此方法在不同文档之间移动节点.如果要从其他文档追加节点,则必须使用document.importNode()方法.
并试图改变秩序.1.css 2.div 3.js喜欢这个,但仍然没有成功......任何人都知道这里发生了什么?
检查上面的代码
编辑7
如您如何执行动态加载的JavaScript块中所述?我将div的innerHTML设置为scripts + content,然后像这样附加到DOM:
检查上面的代码
但仍然没有任何成功.
编辑8
添加了ajax功能代码.xmlhttp.open("GET","http://blabla.com/api/");已尝试过真(异步)和假(同步)的第3个参数.仍然没有成功.
编辑9
功能createDiv()如答案所示:
var dom = parseResponse(responsetext);
var _jr = dom.getElementById('script1'); //<script> tag with src attribute
var _vc = dom.getElementById('script2'); //inline <script> for test purposes only, it should actualy be external script also
var _rv = dom.getElementById('script3'); //inline <script>
var _rw = dom.getElementById('external_div');
var _b = document.getElementsByTagName('body')[0];
var _d = document.createElement('div'); _d.id = 'internal_div';
_d.appendChild(document.importNode(_rw, true));
_d.appendChild(document.importNode(_jr, true));
_d.appendChild(document.importNode(_rv, true)); //without second parameter TRUE, I dont get script content
_d.appendChild(document.importNode(_vc, true)); //without second parameter TRUE, I dont get script content
_b.appendChild(_d);
Run Code Online (Sandbox Code Playgroud)
不行.只有当我从其他文档中获取内联脚本的innerHTML,创建回答中建议的元素,设置他们的innerHTML然后追加当前文档时,才能工作.外部脚本根本不会加载.
编辑10
来自localhost的.htaccess ...:
<Files *.html>
Order Deny,Allow
Deny from all
Allow from 127.0.0.1
</Files>
<Files *.php>
Order Deny,Allow
Deny from all
Allow from 127.0.0.1
</Files>
<Files index.php>
Order Allow,Deny
Allow from all
</Files>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /page1/
#RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
</IfModule>
Run Code Online (Sandbox Code Playgroud)
.htaccess来自192.***......:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /direktexpress/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /page2/index.php [L]
</IfModule>
# END WordPress
Run Code Online (Sandbox Code Playgroud)
编辑11
所以我可能会给予赏金@Drakes,只是为了努力和他花在我的问题上的时间,并将显示一些截图.它肯定是firefox bug,我刚刚测试了chrome并且它有效.
第1张图片:源代码192.168.2.197/testing/whatever/etc..htaccess与上面的示例相同
第二张图片是script.js的源代码,它被加载到192.168.2.197/testing/whatever/etc上..htaccess与上例中的相同:
第3张图是检查员的截图,我的dom看起来如何:
第四张图......没有任何反应.只是一个与我的问题无关的警告(我希望如此),因为即使我删除所有脚本,它仍然会出现.
它是firefox的bug吗?
问题是上面的代码混合appendChild 了innerHTML.在某些情况下,两者的表现不同,这在直觉上并不明显.前者允许新插入的脚本节点在附加到DOM时执行.后者没有.对许多人来说,这一直是一个令人头疼的问题.请使用谷歌"脚本和innerHTML",你会发现你并不是唯一面临这个类似问题的人.
如果你(1)改变了
_d.innerHTML = _jr + _vc + _rv
Run Code Online (Sandbox Code Playgroud)
至
_d.appendChild(document.importNode(_jr));
_d.appendChild(document.importNode(_vc));
_d.appendChild(document.importNode(_rv));
Run Code Online (Sandbox Code Playgroud)
另外(2)改变
var _jr = dom.getElementById('script1').outerHTML;
var _vc = dom.getElementById('script2').outerHTML;
var _rv = dom.getElementById('script3').outerHTML;
Run Code Online (Sandbox Code Playgroud)
至
var _jr = dom.getElementById('script1');
var _vc = dom.getElementById('script2');
var _rv = dom.getElementById('script3');
Run Code Online (Sandbox Code Playgroud)
然后你的脚本将被执行.这是一个演示:
var b = document.getElementsByTagName('body')[0];
/* Works */
var s1 = document.createElement('script');
s1.innerHTML = "console.log('I will execute')";
b.appendChild(s1);
/* Fails */
var s2 = document.createElement('script');
s2.innerHTML = "while(1){alert('Do not worry! I will not execute');}";
b.innerHTML = s2.outerHTML;
console.log("It didn't execute");Run Code Online (Sandbox Code Playgroud)
经测试
我在我的服务器上运行了OP代码以尽可能地复制问题.鉴于提供的代码,我可以使它在我的服务器上按预期工作.我只是将AJAX URL更改http://blabla.com/api/为api.html并提供了我自己的文件,因为OP没有提供,但是我将它应该包含在OP的JavaScript中.以下是示例结果:
的index.html
<html lang="en">
<body>
<script>
(function() {
var e = document.createElement('script'); e.type = 'text/javascript'; e.async = true; e.src = 'script.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(e, s);
})();
</script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
的script.js
这是OP的代码修改为我上面的规范(使用appendChild而不是innerHTML,AJAX调用返回下面的api.html的内容)
function ajaxCall() {
//... some script to send ajax request which calls createDiv() after success
if (window.XMLHttpRequest){
xmlhttp=new XMLHttpRequest();
}
else{
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function(){
if(xmlhttp.readyState==4&&xmlhttp.status==200){
createDiv(xmlhttp.responseText);
}
};
xmlhttp.open("GET","api.html");
xmlhttp.send();
}
function parseResponse(response) {
var parser = new DOMParser();
var dom = parser.parseFromString(response, "text/html");
return dom;
}
function createDiv(responsetext)
{
var dom = parseResponse(responsetext);
var _ws = dom.getElementById('styles');
var h = document.getElementsByTagName('head')[0];
h.appendChild(document.importNode(_ws, true));
var _jr = dom.getElementById('script1');
var _vc = dom.getElementById('script2');
var _rv = dom.getElementById('script3');
var _rw = dom.getElementById('my_div');
var _b = document.getElementsByTagName('body')[0];
var _d = document.createElement('div'); _d.id = 'just_id';
_d.appendChild(document.importNode(_jr, true));
_d.appendChild(document.importNode(_vc, true));
_d.appendChild(document.importNode(_rv, true));
_d.appendChild(document.importNode(_rw, true));
_b.appendChild(_d);
}
ajaxCall();
Run Code Online (Sandbox Code Playgroud)
api.html(由AJAX调用返回)
<!DOCTYPE html>
<html>
<body>
<style type="text/css" id="styles"></style>
<script type="text/javascript" id="script1" src="script1.js"></script>
<script type="text/javascript" id="script2">console.log("incline script 2")</script>
<script type="text/javascript" id="script3">console.log("incline script 3")</script>
<div id="my_div"></div>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
script1.js
console.log("src script1");
Run Code Online (Sandbox Code Playgroud)
以下是DevTools的结果,表明这是有效的.

