如何在 onClick 处理程序内的 JavaScript 代码中转义字符串?

69

也许我想得太多了,但我遇到了一个问题,无法确定在链接的 onClick 处理程序内的某些 JavaScript 代码中使用哪种转义字符串。例如:

也许我想得太多了,但我遇到了一个问题,无法确定在链接的 onClick 处理程序内的某些 JavaScript 代码中使用哪种转义字符串。例如:

<a href="#" onclick="SelectSurveyItem('<%itemid%>', '<%itemname%>'); return false;">Select</a>
<%itemid%><%itemname%>是模板替换发生的地方。我的问题是项目名称可以包含任何字符,包括单引号和双引号。目前,如果它包含单引号,它将中断JavaScript代码。

我的第一个想法是使用模板语言的功能对项目名称进行JavaScript转义,这只会转义引号。这将无法解决包含双引号的字符串导致链接HTML中断的情况。通常如何解决此问题?我需要对整个onClick处理程序进行HTML转义吗?

如果是这样,看起来会非常奇怪,因为模板语言的转义函数也会将括号、引号和分号HTML化...

这个链接是为搜索结果页面中的每个结果生成的,因此在JavaScript标签内创建单独的方法是不可能的,因为我需要为每个结果生成一个方法。

此外,我正在使用公司自制的模板引擎,因此特定于工具包的解决方案对我没有用。

13个回答

80
在JavaScript中,您可以将单引号编码为"\x27",将双引号编码为"\x22"。因此,使用这种方法,一旦您进入JavaScript字符串文字的(双引号或单引号)引号内部,就可以毫无顾虑地使用\x27 \x22,而不必担心任何嵌入式引号“突破”您的字符串。

\xXX用于字符< 127,\uXXXX用于Unicode,因此,掌握了这些知识,您可以为所有超出常规白名单的字符创建一个强大的JSEncode函数。

例如,

<a href="#" onclick="SelectSurveyItem('<% JSEncode(itemid) %>', '<% JSEncode(itemname) %>'); return false;">Select</a>

23

根据服务器端语言的不同,你可以使用以下其中之一:

.NET 4.0

string result = System.Web.HttpUtility.JavaScriptStringEncode("jsString")

Java

import org.apache.commons.lang.StringEscapeUtils;
...

String result = StringEscapeUtils.escapeJavaScript(jsString);

Python

import json
result = json.dumps(jsString)

PHP

$result = strtr($jsString, array('\\' => '\\\\', "'" => "\\'", '"' => '\\"', 
                                 "\r" => '\\r', "\n" => '\\n' ));

Ruby on Rails

<%= escape_javascript(jsString) %>

对于.NET来说,你的答案似乎是唯一的方法。btn.OnClientClick = "return confirm('Are you sure?')";是有效的,但是如果要在其中放置单引号(例如"return confirm('You're sure, right?');"),唯一的方法是进行编码...既不是反斜杠也不是&apos;起作用。 - John Riehl

11
使用隐藏的span,针对每个参数<%itemid%><%itemname%>分别写入它们的值。
例如,<%itemid%>的span将如下所示:<span id='itemid' style='display:none'><%itemid%></span> 并在javascript函数 SelectSurveyItem 中从这些span的 innerHTML 中获取参数。

2
这确实是最佳答案。如果你把值放在<input type=hidden id="itemid" value="<%:itemid%>">中,然后用jQuery $('#itemid').val()获取它们,就不需要特殊处理了。 - Sire

9

尽量避免在HTML中使用字符串文字,而是使用JavaScript绑定JavaScript事件。

此外,避免使用“href=#”,除非您真的知道自己在做什么。它会破坏对于强制中键点击者(标签页打开器)的许多可用性。

<a id="tehbutton" href="somewhereToGoWithoutWorkingJavascript.com">Select</a>

我选择的JavaScript库恰好是jQuery:

<script type="text/javascript">//<!-- <![CDATA[
jQuery(function($){
   $("#tehbutton").click(function(){
        SelectSurveyItem('<%itemid%>', '<%itemname%>');
        return false;
   });
});
//]]>--></script>

如果你需要渲染像这样的链接列表,你可能想要这样做:
<a id="link_1" href="foo">Bar</a>
<a id="link_2" href="foo2">Baz</a>

<script type="text/javascript">
   jQuery(function($){
        var l = [[1,'Bar'],[2,'Baz']];
        $(l).each(function(k,v){
           $("#link_" + v[0] ).click(function(){
                SelectSurveyItem(v[0],v[1]);
                return false;
           });
        });
   });
 </script>

9
如果要放到HTML属性中,您需要对其进行HTML编码(至少将>转换为&gt;<转换为&lt;"转换为&quot;),并转义单引号(使用反斜杠),以便它们不会干扰JavaScript的引用。
最好的方法是使用您的模板系统(必要时进行扩展),但您可以简单地创建几个转义/编码函数,并将它们都包装在要输入的任何数据周围。
是的,即使HTML属性中包含JavaScript,HTML转义整个HTML属性的内容也是完全有效(正确的)。

4

另一个有趣的解决方案可能是这样的:

<a href="#" itemid="<%itemid%>" itemname="<%itemname%>" onclick="SelectSurveyItem(this.itemid, this.itemname); return false;">Select</a>

然后,您可以在变量上使用标准的HTML编码,而不必担心javascript引用的额外复杂性。

是的,这确实创建了严格无效的HTML。但是,这是一种有效的技术,所有现代浏览器都支持它。

如果是我的话,我可能会选择我的第一个建议,并确保值被HTML编码并且单引号被转义。


就个人而言,我认为这种技术是一种不好的将数据与节点关联的方式。http://noteslog.com/metaobjects/ 是一种稍微高级的技术,但它可以让你得到一个有效的页面,并且结果相同。 - Kent Fredric
我完全同意这是一种有点不太优美的解决方案,但它确实可以使一些棘手的问题变得显著更容易。然而这绝对是一个小众修复 ;)"元对象"技术是一种有趣的技巧,虽然本身有点hacky,但我可以看到它会很有用。 - Dan

1

我也遇到过这个问题。我编写了一个脚本,将单引号转换为转义的双引号,以避免破坏 HTML。

function noQuote(text)
{
    var newtext = "";
    for (var i = 0; i < text.length; i++) {
        if (text[i] == "'") {
            newtext += "\"";
        }
        else {
            newtext += text[i];
        }
    }
    return newtext;
}

1

首先,如果将onclick处理程序设置为以下方式,那么它会更简单:

<a id="someLinkId"href="#">Select</a>
<script type="text/javascript">
  document.getElementById("someLinkId").onClick = 
   function() {
      SelectSurveyItem('<%itemid%>', '<%itemname%>'); return false;
    };

</script>

然后需要对itemid和itemname进行JavaScript转义(即"变为\"等)。

如果您在服务器端使用Java,可以查看来自Jakarta常见语言的StringEscapeUtils类。否则,编写自己的“escapeJavascript”方法不应该花费太长时间。


1
在部分声明单独的函数,并在onClick方法中调用它们。如果有很多函数,可以使用一个编号方案对它们进行命名,或者在函数中使用一个大而臃肿的switch语句,在onClick中传递一个整数参数。

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接