<script> 使用 eval 动态执行具有外部 src 属性的标记



我正在使用Genius API检索给定歌曲的歌词,并将它们嵌入HTML <div>标签中。我正在使用PHP与此API进行互动,这是通过AJAX获取请求。

在成功的Ajax请求时,我从PHP中检索以下HTML:

<div id='rg_embed_link_2351532' class='rg_embed_link' data-song-id='2351532'>
    Read <a href='https://genius.com/The-1975-the-sound-lyrics'>“The Sound” by The 1975</a> on Genius
</div> 
<script crossorigin src='//genius.com/songs/2351532/embed.js'></script>

执行时,天才API返回的脚本标签将嵌入歌词和歌词信息。

我正在尝试将此HTML导入我已经存在的<div>。在这种情况下,将不会执行<script>部分。我尝试在AJAX的"成功"功能中使用eval()来动态执行此脚本,但是我没有成功:

$.ajax({
    url: 'lyrics.php',
    type: 'GET',
    async: true,
    success: function(success){
        geniusHTML = success;
        //Insert geniusHTML including script tag into div
        var lyricsDiv = document.getElementById("lyricsDiv");
        lyricsDiv.innerHTML = geniusHTML;
        //Get the script tag from the html and use eval on it
        var innerScript = lyricsDiv.getElementsByTagName('script')
        eval(innerScript.outerHTML);
    }
});

我试图评估:

  • .outerHTML-控制台显示此值为:<script crossorigin="" src="//genius.com/songs/2351532/embed.js"></script>
  • .innerHTML-属性似乎是空的。
  • .src-控制台显示此值为:http://genius.com/songs/2351532/embed.js。使用Uncaught SyntaxError: Unexpected end of inputeval()功能错误。

我觉得我有可能向后做。我应该在之前从ajax return 中执行脚本吗?(该脚本生成很多嵌入式DIV标签)

编辑

通过Answerer sjoerd de wit 的指令,我试图从源标签的src属性创建一个新的脚本标签,然后通过document.head.appendchild添加它。这无效,提供警告:

无法在"文档"上执行"写":不可能写 从异步加载的外部脚本中进入文档,除非 它是明确打开的。

您应该从脚本标签中获得SRC,然后动态创建并加载其在HTML

var script = document.createElement("script");  
var innerScript = lyricsDiv.getElementsByTagName('script')
script.src = innerScript.src; 
document.head.appendChild(script); 

使用jQuery的.html()而不是JavaScript的.innerHTML()将自动评估字符串中的脚本

所以,尝试更改此行

//Insert geniusHTML including script tag into div
var lyricsDiv = document.getElementById("lyricsDiv");
lyricsDiv.innerHTML = geniusHTML;
//Get the script tag from the html and use eval on it
var innerScript = lyricsDiv.getElementsByTagName('script')
eval(innerScript.outerHTML);

进入

$("#lyricsDiv").html(geniusHTML);

解决方案
回答我自己的问题。

这个问题的其他答案是完全可以接受的,并且在大多数情况下起作用。但是,如果外部.js文件在其中包含 document.write ,则您的浏览器将为您提供以下警告:

无法在"文档"上执行"写":除非明确打开,否则不可能从异步加载的外部脚本写入文档。

解决此问题的方法之一是使用 Postscribe 。Postscribe将覆盖文档的任何实例。在JavaScript中传递给它。

在我的代码的上下文中 - 放心,我将重构使其更有效 - 我通过获取元素的extraperhtml从DIV中检索脚本标签,然后我将其传递到Postcribe中。<<<<<<<<<<<<<<<<<<<<<<<</p>

使用此用例,Postcribe需要两个参数。将脚本传递给脚本本身的DIV。当然 - 您可以像我在以下示例中所做的那样传递脚本或通过变量传递脚本:

var myScript = myDiv.getElementsByTagName('script')[0].outerHTML;
postscribe('#myDiv', myScript);

请参阅上面链接的Postscribe文档以获取安装说明和其他功能。

最新更新