获取跨域脚本标记的内容

时间:2013-02-23 11:06:57

标签: javascript cross-domain requirejs innerhtml script-tag

我在JavaScript中创建了一种新的编程语言,我希望用户能够将其包含在他们的网页中,就像使用script标记的任何其他脚本一样:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8"/>
        <title>My Prog Lang</title>
        <script src="scripts/myProgLang.js"></script>
        <script type="text/my-prog-lang" src="scripts/index.mypl"></script>
    </head>
</html>

我们的想法是myProgLang.js将获取所有脚本的内容并执行它们:

window.addEventListener("DOMContentLoaded", function () {
    var scripts = document.querySelector('script[type="text/my-prog-lang"]');
    var length = scripts.length;

    for (var i = 0; i < length; i++) {
        var script = scripts[i];
        var src = script.getAttribute("src");
        var content = AJAX.getSync(src);
        myProgLang.eval(content);
    }
}, false);

这种方法的明显问题(除了进行同步AJAX调用之外)是不同域上的脚本违反了相同的源策略。

显而易见的解决方案是使用脚本加载程序(如RequireJS)使用文本插件将脚本加载为纯文本。

但是我不想仅仅为此任务包含整个RequireJS框架。所以我做了一些挖掘并找到了答案:https://stackoverflow.com/a/4927418/783743

根据以上回答:

  

如果脚本元素为:

,脚本元素的innerHTML属性应该为脚本提供字符串内容。      
      
  • 内联脚本或
  •   
  • 脚本已加载(如果使用src属性)
  •   

不幸的是,这不起作用(至少在Opera上)。无法使用src属性访问使用innerHTML属性加载的脚本。

我还有哪些其他方法可以解决这个问题?

3 个答案:

答案 0 :(得分:2)

您需要发出一个Ajax请求...如果它与该页面的域相同,它将正常加载,如果服务器发送了缓存标头,它应该使用现有的副本。

如果它在另一个域上,您将需要CORS头(在支持的位置)和/或JSONP加载器。

答案 1 :(得分:1)

如果您尝试直接通过标记包含自定义脚本,那么它将无法解析,您将无法获得内部HTML。

我建议使用JSONP风格的方法。首先定义一个全局处理函数,例如

// myproglang.js

window.registerSource = function(source) {
    myProgLang.eval(source);
}

然后在源文件中,将代码包装在对该函数的调用中:

// source.mypl
registerSource("\
Dim foo as Integer;\
")

它有点难看,因为它需要文本文件来转义换行符以保持字符串文字,但除了使用XHR之外,这是我能想到的唯一可行的解​​决方案。

您总是可以为这种“语言”编写一个编译步骤,用"\n"替换"\\\n"并将源包装在registerSource()调用中。只要它是透明的,它就是一个可行的选择。

答案 2 :(得分:1)

此问题已经被问到herehere

基本上,共识是:

  • 如果脚本是内联的,则可以使用script.innerHTML
  • 进行访问
  • 如果它不是内联的,那么只有在你发出另一个ajax请求时才能访问它。 (显然您可能会遇到跨域问题)

注释

如果您的HTTP标头配置正确,您应该可以从浏览器的缓存中获取脚本,因此速度很快。

可以使用脚本主机的Access-Control-Allow-Origin: *标头修复跨域问题。