将 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("&lt;div/&gt;").append(jQuery("&lt;br/&gt;hello&lt;script type='text/javascript'&gt;console.log('gnu!'); &lt;/script&gt;there").remove('script'))。实际上,它仍然运行脚本标签,并且只删除了一个文本节点...有趣... 是的,脚本在$(html) 上执行……看来解决方案是用正则表达式删除脚本元素? 但那是邪恶的:***.com/questions/1732348/… :) 是的,你需要一个真正的解析器,像 json2.js 这样大的东西,但用于删除脚本标签:-)【参考方案3】:

html 中的脚本使用这里提到的所有简单方法为我不断执行,然后我记得 jquery 有一个工具(从 1.8 开始)jQuery.parseHTML。仍然有一个问题,根据属性内的documentation 事件(即&lt;img onerror&gt;)仍然会运行。

这是我正在使用的:

var $dom = $($.parseHTML(d));

$dom 将是一个带有找到的元素的 jquery 对象

【讨论】:

以上是关于将 html 附加到 jQuery 元素而不在 html 中运行脚本的主要内容,如果未能解决你的问题,请参考以下文章

jQuery - 如果所有子元素都具有相同的类,则将附加类添加到页面上的另一个元素

将多个元素附加到 DOM 的 jquery 会丢失排序顺序

:: jQuery :: 将元素附加为区分大小写和非标准的 html 元素

jQuery 在附加到 DOM 之前从元素中生成变量

将数组项附加到具有相应索引的 DOM 元素(jQuery)

如何将 jquery 自动完成附加到输入元素