【问题标题】:How to pass parameters to a Script tag?如何将参数传递给 Script 标签?
【发布时间】:2011-07-14 14:58:25
【问题描述】:

我阅读了 Nic 博士的 XSS Widgets 教程 DIY widgets - How to embed your site on another site

我正在寻找一种将参数传递给脚本标签的方法。例如,要进行以下工作:

<script src="http://path/to/widget.js?param_a=1&amp;param_b=3"></script>

有没有办法做到这一点?


两个有趣的链接:

【问题讨论】:

标签: javascript parameters widget xss script-tag


【解决方案1】:

我很抱歉回答了一个超级老问题,但在花了一个小时与上述解决方案搏斗后,我选择了更简单的东西。

<script src=".." one="1" two="2"></script>

在上面的脚本中:

document.currentScript.getAttribute('one'); //1
document.currentScript.getAttribute('two'); //2

比 jquery OR url 解析容易得多。

您可能需要来自@Yared Rodriguez 的 IE 答案中 doucment.currentScript 的 polyfil:

document.currentScript = document.currentScript || (function() {
  var scripts = document.getElementsByTagName('script');
  return scripts[scripts.length - 1];
})();

【讨论】:

  • 请注意 currentScript 在 IE 中不起作用。 Details
  • polyfill 不再起作用,document.currentScript 是只读的,如果它已经存在则无法分配。也许像 if(!document.currentScript) { *** the polyfill function *** } 这样的不同检查会更好
  • 我很抱歉,大卫,我总是让我的答案通用,以便其他人可以使用该解决方案,而无需初始实施细节增加问题。在我上面的示例中,您可以看到 src="..." 这意味着表示,任何 src,都没有关系 :)
  • @RichardFox 感谢您的回答,但不得不评论说“不回答原始问题:不使用 path/to/widget.js”可能是我读过的最有趣的事情整个星期!不敢相信你回复得这么好。
  • @fadomire 一个真正的 polyfill 应该在 polyfill 之前检查是否存在。只需将其包装为: if(!document.currentScript) {...}
【解决方案2】:

最好使用html5中的功能5 data Attributes

<script src="http://path.to/widget.js" data-width="200" data-height="200">
</script>

在脚本文件http://path.to/widget.js 中,您可以通过这种方式获取参数:

<script>
function getSyncScriptParams() {
         var scripts = document.getElementsByTagName('script');
         var lastScript = scripts[scripts.length-1];
         var scriptName = lastScript;
         return {
             width : scriptName.getAttribute('data-width'),
             height : scriptName.getAttribute('data-height')
         };
 }
</script>

【讨论】:

  • 如果 id="myAwesomeWigretNo1" 不是一直这样,而是 myAwesomeWigretNo2myAwesomeWigretNo681 怎么办?如何解决此问题以接受实变量?
  • 对于它的价值,还有其他方法可以引用脚本,例如document.currentScript(仅适用于不在其自己文件中的脚本)并将id放在&lt;script&gt;上标记,然后通过它找到它。
  • 如果团队中的其他程序员更改了 ID,但不知道您使用了这个 ID,该怎么办?
  • 如果您异步加载脚本,那么使用 ID 是我推荐的唯一可靠选项。谢谢@Thunderforge ...此外,任何程序员都应避免在没有适当的冲刺计划的情况下重构代码,而该计划的人对正在发生的事情有所了解;)
  • 当然,您可以要求开发人员有很强的道德规范,但从长远来看,这不会奏效……人们会忘记东西……在一个好的软件设计中,每个块都应该被隔离,awesome-pixels.tumblr.com/post/101930002170/… en.wikipedia.org/wiki/SOLID_(object-oriented_design) 所以我不认为这是一个好与坏的解决方案,它只是维护 ID 与不维护更复杂 :-) 你不打算加载脚本异步我认为没有理由使用 ID 加载
【解决方案3】:

知道了。有点 hack,但效果很好:

var params = document.body.getElementsByTagName('script');
query = params[0].classList;
var param_a = query[0];
var param_b = query[1];
var param_c = query[2];

我将脚本标签中的参数作为类传递:

<script src="http://path.to/widget.js" class="2 5 4"></script>

This article 帮了大忙。

【讨论】:

  • 这篇文章很棒!
  • 类应该用于样式元素不传递参数。
  • @kspacja 是的,HTML 应该只包含不带样式的内容,除非我们必须为浮动和列布局精确排序 DIV 标签,因为 CSS 实际上无法完成这项工作,而且我们在某种程度上还可以接着就,随即。砍掉,我说。但是如果你想避免冲突或者你是那种会为此失眠的类型,你可以使用“data-”属性。
【解决方案4】:

另一种方法是使用元标记。任何应该传递给 JavaScript 的数据都可以这样分配:

<meta name="yourdata" content="whatever" />
<meta name="moredata" content="more of this" />

然后可以像这样从元标记中提取数据(最好在 DOMContentLoaded 事件处理程序中完成):

var data1 = document.getElementsByName('yourdata')[0].content;
var data2 = document.getElementsByName('moredata')[0].content;

绝对没有 jQuery 或类似的麻烦,没有必要的 hack 和变通方法,并且适用于任何支持元标记的 HTML 版本...

【讨论】:

  • 我认为这种方法是迄今为止最简单的方法。它就像一个魅力,给了我我需要的东西。很好的问题和很棒的解决方案!
  • 我认为在每个参数的
【解决方案5】:

JQuery 有一种将参数从 HTML 传递到 javascript 的方法:

将其放入myhtml.html 文件中:

<!-- Import javascript -->
<script src="//code.jquery.com/jquery-1.11.2.min.js"></script>
<!-- Invoke a different javascript file called subscript.js -->
<script id="myscript" src="subscript.js" video_filename="foobar.mp4">/script>

在同一目录中创建一个subscript.js 文件并将其放入其中:

//Use jquery to look up the tag with the id of 'myscript' above.  Get 
//the attribute called video_filename, stuff it into variable filename.
var filename = $('#myscript').attr("video_filename");

//print filename out to screen.
document.write(filename);

分析结果:

加载 myhtml.html 页面时,'foobar.mp4' 会打印到屏幕上。名为 video_filename 的变量从 html 传递到 javascript。 Javascript 将其打印到屏幕上,并显示为嵌入到父级的 html 中。

jsfiddle 证明上述方法有效:

http://jsfiddle.net/xqr77dLt/

【讨论】:

    【解决方案6】:

    如果您使用 jquery,您可能需要考虑 their data method.

    我在回复中使用了与您尝试的类似的内容,但如下所示:

    <script src="http://path.to/widget.js" param_a = "2" param_b = "5" param_c = "4">
    </script>
    

    您还可以创建一个函数,让您直接获取 GET 参数(这是我经常使用的):

    function $_GET(q,s) {
        s = s || window.location.search;
        var re = new RegExp('&'+q+'=([^&]*)','i');
        return (s=s.replace(/^\?/,'&').match(re)) ? s=s[1] : s='';
    }
    
    // Grab the GET param
    var param_a = $_GET('param_a');
    

    【讨论】:

      【解决方案7】:

      创建一个包含参数列表的属性,如下所示:

      <script src="http://path/to/widget.js" data-params="1, 3"></script>
      

      然后,在您的 JavaScript 中,将参数作为数组获取:

      var script = document.currentScript || 
      /*Polyfill*/ Array.prototype.slice.call(document.getElementsByTagName('script')).pop();
      
      var params = (script.getAttribute('data-params') || '').split(/, */);
      
      params[0]; // -> 1
      params[1]; // -> 3
      

      【讨论】:

      • 这种方法有什么缺点?
      • @Tronathan 这种方法没有真正的缺点,并且包含一个 polyfill 以提供更好的浏览器支持。我在这里看到的唯一缺点是不能在参数中包含逗号,这通常不是问题,您可以通过将分隔符更改为您不打算使用的字符来弥补这一点。
      【解决方案8】:

      感谢 jQuery,一个简单的 HTML5 兼容解决方案是创建一个额外的 HTML 标记,如 div,来存储数据。

      HTML

      <div id='dataDiv' data-arg1='content1' data-arg2='content2'>
        <button id='clickButton'>Click me</button>
      </div>
      

      JavaScript

      $(document).ready(function() {
          var fetchData = $("#dataDiv").data('arg1') + 
                          $("#dataDiv").data('arg2') ;
      
          $('#clickButton').click(function() {
            console.log(fetchData);
          })
      });
      

      上面代码的现场演示:http://codepen.io/anon/pen/KzzNmQ?editors=1011#0

      在现场演示中,可以看到 HTML5 data-* 属性中的数据被连接并打印到日志中。

      来源:https://api.jquery.com/data/

      【讨论】:

      • 浏览了其他一些解决方案,但这是效果最好的一个,而且实施起来也很简单。谢谢!
      • 这应该是公认的解决方案,因为它允许您通过 ID 引用脚本并且是有效的 HTML5。
      【解决方案9】:

      这是一个非常古老的线程,我知道,但如果有人在搜索解决方案后到达这里,这也可能会有所帮助。

      基本上,我使用 document.currentScript 从运行代码的位置获取元素,并使用要查找的变量的名称进行过滤。我使用名为“get”的方法扩展了 currentScript,因此我们可以使用以下方法获取该脚本中的值:

      document.currentScript.get('get_variable_name');
      

      通过这种方式,我们可以使用标准 URI 来检索变量,而无需添加特殊属性。

      这是最终代码

      document.currentScript.get = function(variable) {
          if(variable=(new RegExp('[?&]'+encodeURIComponent(variable)+'=([^&]*)')).exec(this.src))
          return decodeURIComponent(variable[1]);
      };
      

      我忘记了 IE :) 不可能这么简单...好吧,我没有提到 document.currentScript 是 HTML5 属性。它还没有包含在不同版本的 IE 中(我测试到 IE11,它还没有)。为了兼容IE,我在代码中添加了这部分:

      document.currentScript = document.currentScript || (function() {
        var scripts = document.getElementsByTagName('script');
        return scripts[scripts.length - 1];
      })();
      

      我们这里要做的是为 IE 定义一些替代代码,它返回当前脚本对象,在解决方案中需要从 src 属性中提取参数。这不是 IE 的完美解决方案,因为存在一些限制;如果脚本是异步加载的。较新的浏览器应包含“.currentScript”属性。

      希望对你有帮助。

      【讨论】:

        【解决方案10】:

        这是 jQuery 3.4

        的解决方案
        <script src="./js/util.js" data-m="myParam"></script>
        
        $(document).ready(function () {
            var m = $('script[data-m][data-m!=null]').attr('data-m');
        })
        

        【讨论】:

        • 除了 jQuery 实际上已经过时并且已经有很长一段时间了,除了原始问题不要求 jQuery 解决方案。您的解决方案最好使用 document.querySelector().getAttribute() 编写——其他答案中已经提到过。 (并不是说它是“最好的”方式,只是指出 jQuery 解决方案并不是真正必要的。
        【解决方案11】:

        将您需要的值放在其他脚本可以检索它们的地方,例如隐藏输入,然后在您初始化新脚本时从它们的容器中提取这些值。您甚至可以将所有参数作为 JSON 字符串放入一个隐藏字段中。

        【讨论】:

        • 感谢您的回答。参数实际上是由用户输入的(他们在他们的代码中嵌入了这个脚本标签)。然后呢?
        • 如果您无法控制客户端/服务器脚本,我唯一能想到的就是获取用户输入并使用它来生成一个特定的 .js 文件,其中嵌入了他们的输入,这是假设您可以控制收集和处理他们的输入。
        【解决方案12】:

        我想要尽可能多地支持旧浏览器的解决方案。否则我会说currentScriptdata attributes 方法将是最时尚的。

        这是这些方法中唯一没有在这里提出的。特别是,如果由于某种原因您拥有大量数据,那么最好的选择可能是:

        本地存储

        /* On the original page, you add an inline JS Script.
         * If you only have one datum you don't need JSON:
         * localStorage.setItem('datum', 'Information here.');
         * But for many parameters, JSON makes things easier: */
        var data = {'data1': 'I got a lot of data.',
                    'data2': 'More of my data.',
                    'data3': 'Even more data.'};
        localStorage.setItem('data', JSON.stringify(data));
        
        /* External target JS Script, where your data is needed: */
        var data = JSON.parse(localStorage.getItem('data'));
        console.log(data['data1']);
        

        localStorage 拥有完整的现代浏览器支持,并且对旧浏览器的支持也出奇的好,可以追溯到 IE 8、Firefox 3,5 和 Safari 4 [11 年前] 等等。

        如果您没有大量数据,但仍需要广泛的浏览器支持,也许最好的选择是:

        元标记 [by Robidu]

        /* HTML: */
        <meta name="yourData" content="Your data is here" />
        
        /* JS: */
        var data1 = document.getElementsByName('yourData')[0].content;
        

        这样做的缺陷在于,将元标记 [直到 HTML 4] 放置在 head 标记中的正确位置,您可能不希望将这些数据放在那里。为避免这种情况,或将元标记放在正文中,您可以使用:

        隐藏段落

        /* HTML: */
        <p hidden id="yourData">Your data is here</p>
        
        /* JS: */
        var yourData = document.getElementById('yourData').innerHTML;
        

        要获得更多浏览器支持,您可以使用 CSS 类而不是 hidden 属性:

        /* CSS: */
        .hidden {
           display: none;
        }
        
        /* HTML: */
        <p class="hidden" id="yourData">Your data is here</p>
        

        【讨论】:

        • 为每个参数要求一行是笨拙的,但是存储参数。
        • 这是真的,大卫。我在第一种方法中添加了 JSON,使其对许多参数更有效。
        • 在我的回答中,如果您可以不使用参数名称,我会展示一种简单的方法。
        【解决方案13】:

        如果传递不带名称的参数会更简单,就像函数调用一样。

        在 HTML 中:

        <script src="abc.js" data-args="a,b"></script>
        

        然后,在 JavaScript 中:

        const args=document.currentScript.dataset.args.split(',');
        

        现在 args 包含数组 ['a','b']。这假定同步脚本调用。

        【讨论】:

          猜你喜欢
          • 2016-05-09
          • 2022-11-14
          • 2014-10-28
          • 2017-01-12
          • 2017-09-25
          • 2023-03-24
          • 2021-02-11
          • 2011-01-08
          相关资源
          最近更新 更多