将 html 附加到 jQuery 元素而不在 html 中运行脚本
Posted
技术标签:
【中文标题】将 html 附加到 jQuery 元素而不在 html 中运行脚本【英文标题】:Append html to jQuery element without running scripts inside the html 【发布时间】:2011-07-29 20:50:36 【问题描述】:我已经编写了一些代码,它采用 html 字符串并使用 jQuery 从其中清除任何丑陋的 HTML(参见 this SO question 中的早期原型)。它工作得很好,但我偶然发现了一个问题:
当使用 .append() 将 html 包装在 div 中时,代码中的所有脚本元素都会被评估并运行(请参阅 this SO answer 了解为什么会发生这种情况)。我不希望这样,我真的只是希望将它们删除,但只要它们不运行,我以后可以自己处理。
我正在使用此代码:
var wrapper = $('<div/>').append($(html));
我尝试这样做:
var wrapper = $('<div>' + html + '</div>');
但这只会在 IE 中引发 append() 函数修复的“访问被拒绝”错误(请参阅我上面引用的答案)。
我想我可能能够重写我的代码以不需要 html 的包装器,但我不确定,我想知道是否可以在不运行脚本的情况下附加 html,无论如何。
我的问题:
如何包装一段未知的 html 无需在其中运行脚本, 最好完全删除它们?
我应该把 jQuery 扔出窗外吗 并使用纯 javascript 和 而是 DOM 操作?这会有帮助吗?
我不想做的事情:
我不想在客户端放置某种安全层。我非常清楚这将毫无意义。
更新:詹姆斯的建议
James 建议我应该过滤掉脚本元素,但是看看这两个例子(原来的第一个和 James 的建议):
jQuery("<p/>").append("<br/>hello<script type='text/javascript'>console.log('gnu!'); </script>there")
保留文本节点但写入 gnu!
jQuery("<p/>").append(jQuery("<br/>hello<script type='text/javascript'>console.log('gnu!'); </script>there").not('script'))`
不写gnu!,但也会丢失文本节点。
更新 2:
詹姆斯更新了他的答案,我已经接受了。不过,请参阅我对他的回答的最新评论。
【问题讨论】:
【参考方案1】:先删除脚本怎么样?
var wrapper = $('<div/>').append($(html).not('script'));
创建 div 容器
使用纯JS将html放入div
删除 div 中的所有脚本元素
假设html中的脚本元素没有嵌套在其他元素中:
var wrapper = document.createElement('div');
wrapper.innerHTML = html;
$(wrapper).children().remove('script');
var wrapper = document.createElement('div');
wrapper.innerHTML = html;
$(wrapper).find('script').remove();
这适用于 html 只是文本并且 html 在任何元素之外都有文本的情况。
【讨论】:
好主意,它几乎可以工作,但并不完全。我有点粗心地称为 html 的字符串可能包含标签之外的文本,我也想要它。有关示例,请参阅我的更新答案。 此外,根据文档,“html”可能只是文本,没有标签,然后如果将其发送到 $()/jQuery(),jQuery 会将其视为选择器: api.jquery.com/jQuery/#jQuery2 而not()
仅在脚本未包含在另一个元素中时才有效。
这很有希望!稍作修改,它似乎也适用于嵌套脚本:jQuery(wrapper).find('script').remove()
。它可以在 Chrome 中运行,现在我将在 IE 中尝试它 (cringe)
概念证明也适用于 IE。现在我将它添加到我的真实代码中。【参考方案2】:
您应该删除 script
元素:
var wrapper = $('<div/>').append($(html).remove("script"));
第二次尝试:
node-validator 可以在浏览器中使用: https://github.com/chriso/node-validator
var str = sanitize(large_input_str).xss();
另外,phpJS 有一个 strip_tags 函数(基于正则表达式/邪恶): http://phpjs.org/functions/strip_tags:535
【讨论】:
试试这个代码:jQuery("<div/>").append(jQuery("<br/>hello<script type='text/javascript'>console.log('gnu!'); </script>there").remove('script'))
。实际上,它仍然运行脚本标签,并且只删除了一个文本节点...有趣...
是的,脚本在$(html)
上执行……看来解决方案是用正则表达式删除脚本元素?
但那是邪恶的:***.com/questions/1732348/… :)
是的,你需要一个真正的解析器,像 json2.js 这样大的东西,但用于删除脚本标签:-)【参考方案3】:
html 中的脚本使用这里提到的所有简单方法为我不断执行,然后我记得 jquery 有一个工具(从 1.8 开始)jQuery.parseHTML
。仍然有一个问题,根据属性内的documentation 事件(即<img onerror>
)仍然会运行。
这是我正在使用的:
var $dom = $($.parseHTML(d));
$dom 将是一个带有找到的元素的 jquery 对象
【讨论】:
以上是关于将 html 附加到 jQuery 元素而不在 html 中运行脚本的主要内容,如果未能解决你的问题,请参考以下文章
jQuery - 如果所有子元素都具有相同的类,则将附加类添加到页面上的另一个元素