我正在更新我的应用程序,我决定使用不再具有jquery依赖关系的bootstrap 5,并从我的应用中消除这种依赖关系。
因此,我正在将javscript部分从jquery重写为jsvanilla。
我经常使用AJAX来加载不同div中的内容,并根据用户触发的某些事件对其进行后续操作。不幸的是,在某些情况下,我发现自己被迫将脚本标记与html部分挂在一起,以运行无法以任何其他方式执行的javascript函数。
例如:
<script>myFuncrion(val1, val2, val3);</script>
<div id="myDiv">
<div>Other html code ..</div>
</div>
使用jquery,类似这样的东西就足以将标记附加到给定的div并执行javascipt函数
$('#elementToAppend').append(html);
将其转换为香草js我得到了类似的东西
document.getElementById('elementToAppend').innerHTML = html;
所有内容都被正确地附加,但很明显js并没有被执行
我不知道jquery在幕后,但我认为它正在以某种方式被操纵,以便运行javascript部分。
然后我创建了一个函数,可以让恢复正常工作
const functionOne = (elem) => {
// I make the AJAX call...
let jsAndData = getJsAndData(data);
// Append the html string
document.querySelector(elem).innerHTML = jsAndData.cleanData;
// I run the js
eval(jsAndData.js);
}
const getJsAndData = data => {
var js = "";
// Check if there is a <script> tag
let script = data.match(/<script>(.*?)</script>/g);
// If there is a script tag I extrapolate the js content
if (script) {
script.map(val => {
js = val.replace(/</?script>/g, "");
});
// I remove the <script> tag and its content from the html string
let cleanData = data.replace(/<script[^>]*>.*</script>/gm, "");
return { cleanData: cleanData, js: js };
} else {
return { cleanData: data, js: js };
}
};
通过这种方式,我得到了与jquery相同的结果,甚至更好,因为在DOM上不再有任何脚本标记的踪迹
现在,我的问题是:
- 我做的事情对吗
- 有更好的方法吗
- 我是不是完全躲开了
您的方式是正确的。出于安全原因(XSS(,使用innerHTML时不运行脚本标记。
https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML#security_considerations
替代方案:在MDN中,你可以找到这样的破解代码,在不接触前端的情况下从后端处理。我不建议这样做。
const name = "<img src='x' onerror='alert(1)'>";
el.innerHTML = name; // shows the alert