执行<脚本>使用 .innerHTML 插入的元素脚本>
我有一个脚本,它使用 innerHTML
将一些内容插入到元素中。
例如,内容可以是:
<script type="text/javascript">alert('test');</script>
<strong>test</strong>
问题是 标记内的代码没有被执行。
我用谷歌搜索了一下,但没有明显的解决方案。如果我使用 jQuery
$(element).append(content);
插入内容,则脚本部分在注入 DOM 之前会进行 eval
处理。
有谁有执行所有 元素的代码片段吗? jQuery 代码有点复杂,所以我无法真正弄清楚它是如何完成的。
I've got a script that inserts some content into an element using innerHTML
.
The content could for example be:
<script type="text/javascript">alert('test');</script>
<strong>test</strong>
Problem is that the code inside the <script>
tag doesn't get executed.
I googled it a bit but there were no apparent solutions. If I inserted the content using jQuery $(element).append(content);
the script parts got eval
'd before being injected into the DOM.
Has anyone got a snippet of code that executes all the <script>
elements? The jQuery code was a bit complex so I couldn't really figure out how it was done.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(25)
@joshcomley 答案的简化 ES6 版本并附有示例。
没有 JQuery,没有库,没有 eval,没有 DOM 更改,只有纯 Javascript。
http://plnkr.co/edit/MMegiu?p=preview
用法
Simplified ES6 version of @joshcomley's answer with an example.
No JQuery, No library, No eval, No DOM change, Just pure Javascript.
http://plnkr.co/edit/MMegiu?p=preview
Usage
对于您的问题,这是一个非常有趣的解决方案:
http://24ways.org/2005/have-your-dom -and-script-it-too
所以它看起来像这样:
Here is a very interesting solution to your problem:
http://24ways.org/2005/have-your-dom-and-script-it-too
So it would look like this instead:
您不应该使用innerHTML 属性,而应该使用Node 的appendChild 方法:文档树[HTML DOM] 中的节点。这样您就可以稍后调用注入的代码。
确保您了解
node.innerHTML
与node.appendChild
不同。您可能需要花一些时间阅读 Javascript Client Reference 以了解更多详细信息和 DOM。希望以下内容有所帮助...样品注入有效:
You should not use the innerHTML property but rather the appendChild method of the Node: a node in a document tree [HTML DOM]. This way you are able to later call your injected code.
Make sure that you understand that
node.innerHTML
is not the same asnode.appendChild
. You might want to spend some time on the Javascript Client Reference for more details and the DOM. Hope the following helps...Sample injection works:
OP 的脚本在 IE 7 中不起作用。在 SO 的帮助下,下面的脚本可以:
The OP's script doesn't work in IE 7. With help from SO, here's a script that does:
这是一个更短、更高效的脚本,也适用于具有
src
属性的脚本:注意:虽然
eval
如果使用不当可能会导致安全漏洞,但它比动态创建脚本标签快得多。Here's a shorter, more efficient script that also works for scripts with the
src
property:Note: whilst
eval
may cause a security vulnerability if not used properly, it is much faster than creating a script tag on the fly.试试这个片段:
Try this snippet:
它可以在我的项目中的 Chrome 中运行
It works in Chrome in my project
一种不使用“eval”的解决方案:
这本质上是克隆脚本标签,然后用新生成的脚本标签替换被阻止的脚本标签,从而允许执行。
A solution without using "eval":
This essentially clones the script tag and then replaces the blocked script tag with the newly generated one, thus allowing execution.
使用 https://stackoverflow.com/a/62641523/3394495 中的简短而甜蜜的方法:
它首先解析 HTML到
DocumentFragement
(使用 createContextualFragment< /a> 所有现代浏览器都支持),然后将其添加到 DOM 中。这将执行内联脚本。
Using the short and sweet approach from https://stackoverflow.com/a/62641523/3394495 :
It first parses the HTML to a
DocumentFragement
(using createContextualFragment which is supported in all modern browsers) and then adds that to the DOM.This will execute inline scripts.
scriptNode.innerHTML = code
不适用于 IE。唯一要做的就是替换为scriptNode.text = code
并且它可以正常工作scriptNode.innerHTML = code
didn't work for IE. The only thing to do is replace withscriptNode.text = code
and it work fine使用 jquery
$(parent).html(code)
而不是parent.innerHTML = code
更容易:这也适用于使用
document.write< 的脚本/code> 和通过 src 属性加载的脚本。不幸的是,即使这也不适用于 Google AdSense 脚本。
It's easier to use jquery
$(parent).html(code)
instead ofparent.innerHTML = code
:This also works with scripts that use
document.write
and scripts loaded viasrc
attribute. Unfortunately even this doesn't work with Google AdSense scripts.试试这个,它对我在 Chrome、Safari 和 Safari 上都有效。 Firefox:
但需要注意的一件事是,以下 div 嵌套脚本将不会运行:
要运行脚本,必须将其创建为节点,然后将其附加为子节点。您甚至可以在之前注入的 div & 中附加脚本。它将运行(我之前在尝试让广告服务器代码工作时遇到过这个):
Try this, it works for me on Chrome, Safari & Firefox:
One thing to note though, is that the following div-nested script will NOT run:
For a script to run it has to be created as a node then appended as a child. You can even append a script inside a previously injected div & it will run (I've run into this before when trying to get ad server code to work):
通过正常的 .innerHTML 执行脚本元素只是不要将“”开始和结束标记放在 .innerhtml 值中。看看我的代码,它就像普通代码一样简单,没有 jQuery 或任何其他长 JavaScript 函数
Execute script element by normal .innerHTML just don't put "" start and closing tags in .innerhtml value. Have a look on my code, it's just simple as normal code no jQuery or any other long JavaScript function
从拉里的延伸出来。我让它递归地搜索整个块和子节点。
该脚本现在还将调用使用 src 参数指定的外部脚本。
脚本被附加到头部,而不是按照它们被发现的顺序插入和放置。因此,保留了特定的顺序脚本。每个脚本都是同步执行的,类似于浏览器处理初始 DOM 加载的方式。因此,如果您有一个从 CDN 调用 jQuery 的脚本块,并且下一个脚本节点使用 jQuery...没问题!哦,我根据您在标记参数中设置的内容使用序列化 ID 标记了附加脚本,以便您可以找到此脚本添加的内容。
Extending off of Larry's. I made it recursively search the entire block and children nodes.
The script now will also call external scripts that are specified with src parameter.
Scripts are appended to the head instead of inserted and placed in the order they are found. So specifically order scripts are preserved. And each script is executed synchronously similar to how the browser handles the initial DOM loading. So if you have a script block that calls jQuery from a CDN and than the next script node uses jQuery... No prob! Oh and I tagged the appended scripts with a serialized id based off of what you set in the tag parameter so you can find what was added by this script.
用 TypeScript 制作了这个新的辅助函数,也许有人会欣赏它。如果从脚本参数中删除类型声明,它将只是普通的 JS。
Made this new helper function in TypeScript, maybe someone will appreciate it. If you remove type declaration from script parameter it will just be plain JS.
您可以查看这篇文章。代码可能如下所示:
You may take a look at this post. The code might look like this:
感谢 Larry 的脚本,它在 IE10 中运行得非常好,这就是我所使用的:
Thanks to Larry's script, which worked perfectly well in IE10, this is what I've used:
这是我在最近的项目中的解决方案。
Here is my solution in a recent project.
扩展 Lambder 的答案
您可以使用 base64 图像来创建和加载脚本
或者如果您有
Iframe
您可以使用它Expending the answer of Lambder
You can use base64 image to create and load your script
Or if you have a
Iframe
you can use it instead我需要类似的东西,但需要保留脚本或在与原始脚本相同的位置重新创建脚本,因为我的脚本以 DOM 中脚本标记的位置为目标来创建/目标元素。我还使脚本递归,以确保它在向下一级以上时也能正常工作。
注意:我在这里使用
const
,如果你有旧的浏览器,只需使用var
。I needed something similar, but needed the script to remain or be re-created in the same spot as the original script, since my script targets the location of the script tag in the DOM to create/target elements. I also made the script recursive to make sure it also works if it is more than one level down.
NOTE: I use
const
here, if you have a older browser, just usevar
.只要这样做:
Just do:
我还有一些页面需要在加载 javascript 文件后执行 javascript 代码(使用 eval),因此将加载事件放在脚本 createelement 上,以便在加载 javascript 文件时执行。我的网站是一个 MVC SPA 应用程序。它使用 ajax 加载部分页面。这些部分页面使用innerhtml设置,然后加载javascript文件和该部分页面上的javascript代码。
I had also pages that needed to execute javascript code (with eval) after the javascript files are loaded so did put load events on the script createelement so when the javascript file(s) were loaded gets executed. My website is a MVC SPA application. It loads partial pages with ajax. Those partial pages are set with innerhtml and then the javascript files are loaded and the javascript code on thst partial page.
我刚刚在元素中将appendChild 与我的脚本一起使用,如下所示:
它开始按预期工作!
I just used appendChild with my script in the element like this :
And it starts to work as expected!
从问题中提取的答案
通过查看 jQuery 代码,我设法弄清楚 jQuery 是如何做到这一点的,从而产生了以下代码:
Answer extracted from the question
By peeking into the jQuery code I've managed to figure out how jQuery does it, which resulted in the following code:
尝试函数 eval()。
这是我正在开发的项目中的一个真实示例。
感谢这篇帖子
Try function eval().
This is a real example from a project that i am developing.
Thanks to this post