【问题标题】:Chain style html markup链式 html 标记
【发布时间】:2011-06-10 07:43:58
【问题描述】:

动机和问题

有几个使用 ruby​​ 生成 html 标记字符串的库(erb、haml、builder、markaby、tagz、...),但我对其中任何一个都不满意。原因是,除了erb之外,它们都采用嵌套样式而不是链样式。而erb是一种在html中嵌入ruby而不是用ruby生成html的方法。

据我了解,ruby 的一大优点在于鼓励使用链式样式:

receiver.method1(args1).method2(args2). ... method_n(args_n)

而不是做嵌套样式:

method_n(...method2(method1(receiver, args1), args2), ... args_n)

但上面提到的库(erb 除外)采用嵌套样式(有时借助块参数)。

我的想法

为了我自己的目的,我写了一个方法dom,这样我就可以用链式的方式来做html标记。当应用于字符串时,这个例子

"This is a link to SO".dom(:a, href: "http://stackoverflow.com").dom(:body).dom(:html)

将生成:

<html><body><a href="http://stackoverflow.com";>This is a link to SO</a></body></html>

当应用于数组时,这个:

[
  ["a".dom(:td), "b".dom(:td)].dom(:tr),
  ["c".dom(:td), "d".dom(:td)].dom(:tr)
].dom(:table, border: 1)

会生成

<table border="1";>
  <tr>
    <td>"a"</td>
    <td>"b"</td>
  </tr>
  <tr>
    <td>"c"</td>
    <td>"d"</td>
  </tr>
<table>

并且,当在没有显式接收器的情况下应用时(在字符串和数组域之外),

dom(:img, src: "picture.jpg", width: 48, height: 48)

会生成

<img src="picture.jpg";width="48";height="48";/>

请注意,只需一种方法dom 即可完成所有操作。这比使用其他库要简单得多。它也很灵活,不受html标签库存变化的影响;您只需使用符号参数指定它。在其他库中,每个标签都有类和/或方法。此外,与 erb 不同,它是纯红宝石。它不是需要转换的DSL。

我的实现

实现如下:

class Hash
    def attribute
        map{|k, v| %Q{#{k}#{
            case v
            when TrueClass; ''
            when Hash;       %Q{="#{v.subattribute}"}
            else             %Q{="#{v}"}
            end
        ;}}}.join
    end
    def subattribute
        map{|k, v| %Q{#{k}:#{v};}}.join
    end
end

class Array
    def dom type, hash = {}
        "<#{type} #{hash.attribute}>\n#{join("\n").gsub(/^/, "  ")}\n</#{type}>"
    end
end

class String
    def dom type, hash = {}
        "<#{type} #{hash.attribute}>#{self}</#{type}>"
    end
end

class Object
    def dom type, hash = {}
        "<#{type} #{hash.attribute}/>"
    end
end

问题

  • 是否已经有稳定的库可以做类似的事情?
  • 这种方法(尤其是我的实现或在链中执行此方法)会出现哪些潜在问题?
  • 某些属性采用布尔值,通常鼓励将其省略。例如,&lt;input type="text";readonly&gt; 而不是 &lt;input type="text";readonly="true"&gt;。在我目前的实现中,我可以通过传递true(最终不会使用)作为dom(:input, type: "text", readonly: true)等属性的值来做到这一点,但这似乎是多余的,也是我拥有@的部分原因代码中的 987654336@ 语句,使其变慢。有没有更好的方法来做到这一点?
  • 是否对实施有任何可能的改进?

【问题讨论】:

    标签: html ruby templates chaining


    【解决方案1】:

    haml 和大多数其他嵌套内容的主要原因是基本上很容易查看 HTML 是如何嵌套的。我假设这一点,但您实际上是编写 HTML 代码还是做更多的后端工作?原因是在嵌套样式中,您将看到元素是如何嵌套的(如果您也在编写样式,这对您很重要)

    虽然写起来很容易

     .dom(:body).dom(:html)
    

    如果没有映射并尝试在脑海中可视化,设计人员很难看到 HTML 是如何流动的,而:

     %html
       %body
    

    一看就知道了。

    不要再举一个例子了:

     "This is a link to SO".dom(:a, href: "http://stackoverflow.com").dom(:body).dom(:html)
    

    如果说客户或您需要在链接中添加可点击的图像,对您来说会更容易吗?你会怎么做?在haml中很简单:

     %html
       %body
         %a{:href => "blah"}
           = image_tag("image.png")
    

    另外,恕我直言,为每个 html 标签编写 dom(:) 就像为其编写结束标签一样乏味(HAML 和其他人已修复)

    再一次,这些只是我从一个 XHTML/CSS 程序员的观点(而不是一个 ruby​​ 程序员的观点)

    最后,我还认为这可以变成一个社区维基或其他东西,因为这不值得一个确切的答案,并且可能会产生很多像这样的主观答案。

    【讨论】:

    • 感谢您的回答。所以问题主要是偏好,没有特别的性能问题?我可能会按照你的建议把它变成一个社区维基。我不做大量的 HTML 编码。只是为了我个人的事情。对我来说,链式风格比嵌套式更容易看到。如果结构复杂,我会使用数组,我会缩进它以使结构清晰。不同之处在于您是在开头还是结尾创建嵌套标签堆栈。我觉得后者对我自己来说更容易。
    • (顺便说一句,我也觉得使用反向波兰表示法比使用中缀或波兰语更​​舒服)。对于带有可点击图像的示例,我认为用image_tag("image.png") 替换初始字符串没有任何困难。我背后的总体思路是,标签和属性是修饰符,而不是主角。有主弦更自然,不断地一步步修改。而对于dom 很乏味的建议,我可以想一个更短的方法名。
    • 嗯,我想这将是一个有效的论据。但是,是的,如果您更喜欢反向波兰符号,我想这更像是一种偏好。 HTML 编码员通常需要找到巢穴,所以如果我把它反过来,我自己就会迷失方向。我还想指出并询问您将如何编写子 div 或 lis?与您对表格的处理方式相同吗?
    • 另外,内联标记呢? HAML 因其“肮脏”的内联标记行为而受到批评,因此在这种情况下更倾向于使用降价。考虑这个链接:chriseppstein.github.com/blog/2010/02/08/haml-sucks-for-content
    • @corroded Child div 或 li 一样。如果只有一个孩子,那将是一条链子。如果有多个,我将使用一个数组。感谢您的链接。我正在阅读它。我如何把它变成一个社区维基?我从来没有做过。我阅读了 meta SO 中的说明,但似乎找不到方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-27
    • 1970-01-01
    • 1970-01-01
    • 2019-03-27
    • 2012-06-24
    • 2014-03-11
    • 1970-01-01
    相关资源
    最近更新 更多