【问题标题】:refactor HTML-generating JavaScript重构 HTML 生成的 JavaScript
【发布时间】:2008-10-29 15:50:17
【问题描述】:

不幸的是,在我的项目中,我们在 JavaScript 中生成了很多这样的 HTML 代码:

var html = new StringBuffer();
html.append("<td class=\"gr-my-deals\"><a href=\"").append(deal.url).append("\" target=\"_blank\">").append(deal.description).append("</a></td>");

我对此有 2 个具体的投诉:

  1. 在 HTML 字符串中使用转义双引号 (\”)。这些应替换为单引号 (') 以提高可读性。
  2. 使用 .append() 代替 JavaScript 字符串连接运算符“+”

应用这两个建议,生成以下等效的代码行,我认为它更具可读性:

var html = "<td class=’gr-my-deals’><a href=’" + deal.url + "’ target=’_blank’>" + deal.description + "</a></td>";

我现在正在寻找一种将第一行代码自动转换为第二行的方法。到目前为止,我想出的只是对我们所有的 Javascript 代码运行以下查找和替换:

Find:    ).append(  
Replace: +

这会将上面显示的代码行转换为:

html.append("<td class=\"gr-my-deals\"><a href=\"" + deal.url + "\" target=\"_blank\">" + deal.description + "</a></td>)";

这应该安全地删除除第一个“append()”语句之外的所有语句。不幸的是,我想不出任何安全的方法来自动将转义的双引号转换为单引号。请记住,我不能简单地进行查找/替换,因为在某些情况下您确实需要使用转义的双引号。通常,这是在您生成包含嵌套 JS 的 HTML 时,并且该 JS 包含字符串参数,例如

function makeLink(stringParam) {

  var sb = new StringBuffer();
  sb.append("<a href=\"JavaScript:myFunc('" + stringParam + "');\">");
}

我的问题(最后)是:

  • 有没有更好的方法可以安全地将对“append()”的调用替换为“+”
  • 有什么方法可以安全地将转义的双引号替换为单引号,正则表达式?

干杯, 唐

【问题讨论】:

    标签: javascript html string-concatenation


    【解决方案1】:

    考虑切换到JavaScript template processor。它们通常相当轻巧,并且可以显着提高代码的清晰度......以及性能,如果您有很多重用并选择一个预编译模板。

    【讨论】:

    • 不管怎样,我不会尝试自动转换这样的代码。尽管现有的东西很丑陋,但引入细微错误的风险更大。当您遇到它们时,请使用更好的方法手动替换出现的情况。
    • John Resig 的“微模板”是一段非常高效且非常简洁的代码。如果您正在寻找一种让同事多加注意的方法,它也很有效。这是您链接的帖子中的某处,但我会再次发布:ejohn.org/blog/javascript-micro-templating
    • 这是一个很好的建议,但不是短期内我真的只是在寻找一种自动化的方法来改进代码(例如查找替换)
    【解决方案2】:

    这是一个 stringFormat 函数,有助于消除连接和丑陋的替换值。

    function stringFormat( str ) {
    
        for( i = 0; i < arguments.length; i++ ) {
            var r = new RegExp( '\\{' + ( i ) + '\\}','gm' );
    
            str = str.replace( r, arguments[ i + 1 ] );    
        }
        return str;
    }
    

    像这样使用它:

    var htmlMask = "<td class=’gr-my-deals’><a href=’{0}’ target=’_blank’>{1}</a></td>";
    
    var x = stringFormat( htmlMask, deal.Url, deal.description ); 
    

    【讨论】:

    • 谢谢,但理想情况下,我需要一种在大量文件上运行此功能的方法。如果有一个类似的函数可用作 Perl 脚本,那可能就可以了。
    【解决方案3】:

    正如 Shog9 所暗示的,市面上有几个优秀的 JavaScript 模板引擎。这是你如何使用我的示例,jQuery Simple Templates

    var tmpl, vals, html;
    
    tmpl  = '<td class="gr-my-deals">';
    tmpl += '<a href="#{href}">#{text}</a>';
    tmpl += '</td>';
    
    vals  = {
        href : 'http://example.com/example',
        text : 'Click me!'
    };
    
    html  = $.tmpl(tmpl, vals);
    

    【讨论】:

      【解决方案4】:

      在 JavaScript 中应该使用 StringBuffer() 而不是字符串连接是有充分理由的。 StringBuffer() 及其 append() 方法使用 Array 和 Array 的 join() 将字符串组合在一起。如果您有大量要连接的部分字符串,已知这是一种更快的方法。

      【讨论】:

      • 也许更快,但我认为速度的提高不值得以可维护性为代价。
      • 每个人都有自己的——你所说的方法并不是每个开发人员都可以维护的。 FTW,提到的模板系统,包括 John Resig 的方法,使用 Array 和 join()。
      • @hal10001:你是正确的 WRT 性能(并不是说它应该对所提到的简短示例产生很大影响)。但是 StringBuffer.append() 非常冗长。使用数组文字 + join() ( ["", deal.description, ""].join("") )更可取。
      【解决方案5】:

      模板?模板很烂!这是我编写代码的方式:

      TD({ "class" : "gr-my-deals" },
         A({ href : deal.url,
             target : "_blank"},
           deal.description ))
      

      我使用一个名为 DOMination 的 20 行库,我会将其发送给任何需要的人,以支持此类代码。

      优势是多方面的,但其中一些最明显的是:

      • 清晰、直观的代码
      • 易学易写
      • 紧凑的代码(没有关闭标签,只有右括号)
      • 被支持 JavaScript 的编辑器、压缩器等很好理解
      • 解决了一些特定于浏览器的问题(例如 IE 上的 rowSpan 和 rowspan 之间的区别)
      • 与 CSS 很好地集成

      (顺便说一句,您的示例突出了 DOMination 的唯一缺点:任何 HTML 属性也是 JavaScript 保留字,在这种情况下 class 必须被引用,以免发生坏事。)

      【讨论】:

        猜你喜欢
        • 2014-08-30
        • 1970-01-01
        • 2016-08-11
        • 2012-06-19
        • 2011-02-27
        • 2019-01-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多