我正在尝试创建一个使用AJAX刷新其内容,样式和脚本的Web应用程序,因此该站点无需重新加载页面即可更新所有内容。
所以会发生的事情是我首先得到页面,当它加载时我使用ajax向服务器发出请求并获取html内容然后另一个请求获取样式,最后另一个请求获取脚本并将其放入脚本标记
<script> //The script goes here </script>
然后,我将脚本标记放在html内容的末尾,并使用内容完全更新正文
<body>
The HTML content goes here
<script> //and here is the script </script>
</body>
请求成功,内容加载,因此样式和我使用浏览器检查器工具时,我可以看到脚本标记内加载的脚本,但脚本不执行。
这是对问题的概述,你可以在这里看到代码https://codepen.io/Yousef-Essam/project/editor/ZJGxea
app.js提供index.html文件,然后索引文件获取script.js文件,该文件使用ajax发送两个请求以获取content.html文件和content.js文件,并将链接标记的href属性设置为样式文件。然后将content.js文件放在带有新内容的脚本标记内。虽然加载了content.html和样式文件,并且脚本标记中加载了脚本,但脚本不会执行。
为什么会发生这种情况,我该如何解决?
--Update--
问题可能在于使用innerHTML,但为什么它不能真正起作用。
此外,我认为eval可能是一个解决方案,但我想要一个更好的解决方案,因为不鼓励使用eval
这太长了,不能发表评论,所以我发布作为答案。
你正确地注意到:
我认为eval可能是一个解决方案,但我想要一个更好的解决方案因为不鼓励使用eval
事实上,eval在任何语言中都存在问题,因为它实际上允许正在运行的程序将字符串视为代码。这个问题的一个大问题就是打开了代码注入的大门(在外行的术语:黑客攻击)。但这个建议更多的是理论建议,而不是建议使用什么功能。
eval
的建议是什么意思?Eval是允许将字符串解释为代码的任何函数或机制。不同的语言具有不同的功能或特征,允许eval
发生。例如,某些语言允许递归字符串插值。有些语言有一个名为interp()
的函数,它产生一个子解释器。有些语言字面上有一个名为eval()
的函数。
Javascript有四种评估机制:
eval()
函数。
传递给eval()
的任何字符串都被视为代码。src
属性
假设src
属性的值是要下载的javascript文件
这适用于文字代码(HTML本身的实际代码)或动态生成的脚本标记(在javascript中创建脚本元素并设置它的src属性)innerHTML
设置脚本体是被禁止的(并且自从Netscape 4以来 - 第一个使用javascript的浏览器)javascript:
URI协议
:
之后的所有内容都被视为代码
这仅在用户单击链接时有效所以,你要做的是执行eval
。你使用eval
函数天气并不重要,你仍然试图使用eval
做innerHTML
(虽然它不起作用)
eval
,有没有一种安全的方式在页面上运行javascript?有 - 至少对于现代浏览器。
现代浏览器实现了一个名为subresource integrity的功能。不幸的是,在写这个答案时,Edge不支持它。基本上你可以计算js文件的哈希值(例如sha1)并在脚本标记中声明它,这样浏览器就可以确认js文件没有被篡改过。以下是一个例子:
<script src="https://cdn.example.com/script.js"
integrity="sha384-+/M6kredJcxdsqkczBUjMLvqyHb1K/JThDXWsBVxMEeZHEaMKEOEct339VItX1zB"></script>
这取决于。 eval
问题可能对你很重要。如果是这样,从设置了子资源完整性的外部源加载javascript是执行javascript的唯一安全方法。
但并不是每个人都是那种偏执狂。到目前为止,我们一直没有这个功能。无论您使用脚本标记还是调用eval()
,以下是一些可以减轻评估代码的经验法则:
<
和>
以及"
或逃避特殊字符等特殊字符。甚至还有一些库可以帮到你。基本上我们想要避免的是像用户输入他们的名字John"; console.log("gotcha");"
并以某种方式能够执行代码的情况。
HTML规范禁止使用innerHTML
解析在页面加载后动态添加为HTML标记的SCRIPT元素(根据生活标准中的note under the text property description)。
如果没有使用eval
来解析脚本的类似问题的答案在简单的搜索中并不明显 - 虽然它们可能存在,但我只看到异地提供的替代技术。
这是一个不使用eval
的动态加载器。因为加载脚本是异步的,所以它使用(err, data
)类型的回调函数来指示何时可以调用脚本。
function loadScript( url, callback) {
var el = document.createElement("SCRIPT");
el.type = "text/javascript";
function finish( err) {
callback( err, err ? false : true);
}
el.onerror = finish;
if( el.readyState){ // <= IE 10
el.onreadystatechange = function(){
if( this.readyState == "complete"){
finish( null);
}
};
}
else {
el.onload = function() { finish(null) };
}
el.setAttribute("async", true);
el.src = url;
document.getElementsByTagName("HEAD")[0].appendChild( el);
}
// example call to load jQuery 3.2.1
loadScript( "https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js",
function (err, ok) {
if( err) {
console.log( "loading failed: " + err);
}
else {
console.log( "loading success");
}
}
);