Handlebars.js: 把手在桌子上不起作用

创建于 2013-08-15  ·  37评论  ·  资料来源: handlebars-lang/handlebars.js

http://jsfiddle.net/cwYhN/3/

请注意,在桌子外时,相同的把手 #each 会成功。 我的 jsfiddle 包含两个带边框的输出来证明这一点。

最有用的评论

我知道这个问题已经很老了,但由于 Sendgrid 的电子邮件模板编辑器没有遵循这些最佳实践,我最近遇到了这个问题。 如果其他人因为这个原因从 Google 解决了这个问题,一个解决方法是将把手代码放在 HTML 注释中。

<table >
  <tbody>
    <!-- {{#each items}} -->
    <tr>
      <td>{{this.key}}</td>
      <td>{{this.value}}</td>
    </tr>
    <!-- {{/each}} -->
  </tbody>
</table>

产生以下输出

<table>
  <tbody>
    <!--  -->
    <tr>
      <td>my key</td>
      <td>my value</td>
    </tr>
    <!--  -->
    <!--  -->
    <tr>
      <td>my key 2</td>
      <td>my value 2</td>
    </tr>
    <!--  -->
  </tbody>
<table>

(注意:我没有直接用 Handlebars 验证过,只是在 Sendgrid 的模板编辑器上)

所有37条评论

值得一提的是,如果 {{each}} 标签放置在表格之外,其他标签也可以使用。 如果重复复制表格,这当然会产生不良影响,但也许它有助于缩小问题的范围:

http://jsfiddle.net/cwYhN/6/

这看起来可能是 jQuery 或其他东西的问题......当你执行console.log(frag);你会看到{{#each}}帮助器甚至在尝试用把手编译它之前就被推到了表之外...

我更新了 jsfiddle 将模板放在<script type="text/x-handlebars-template"></script>标签中,它似乎工作正常......

http://jsfiddle.net/doowb/6GdPy/1/

是的,我刚刚发现自己:
http://jsfiddle.net/cwYhN/10/

就其价值而言,我认为是浏览器丢弃了它认为无效的 html,而不是 jquery 缺陷。

是的,我不确定它是 jQuery 的东西还是 jQuery 调用的本机浏览器函数。 无论哪种方式,它都不喜欢tbodytr之间的{{ }} tr

如果车把以某种方式构建以在此约束内操作,那就太好了。 例如,能够将“每个”放在标签中,同时隐含理解它会迭代标签的内容。 我可能想象它看起来像:

<table>
  <tbody handlebars="{{each}}">
    ... these get iterated ...
  </tbody>
</table>

允许这样的事情会阻止浏览器剥离重要的 each 语句,并且它可以捎带它所属的结束标记 (/tbody)

正如你们已经提到的那样,HTML 解析器被把手标记混淆了,并将其作为您尝试转换为把手模板的 DOM 结构:

            {{#each activity}}

            {{/each}}
        <table style="border:1px solid #ccc;">
        <thead>
            <tr><th>Month</th>
            <th>Imps</th>
            <th>Clicks</th>
            <th>Spend</th>
        </tr></thead>
        <tbody><tr>
                <th>{{month}}</th>
                <td>{{impressions}}</td><td>{{clicks}}</td><td>{{spend}}</td>
            </tr></tbody>
    </table>

应该使用类似上面的脚本行为、javascript 字符串或预编译来解决这个问题。

关闭它,因为这个问题更多的是浏览器实现细节,而不是车把本身的错误。

浪费了半天才发现 {{#each}} 在表中不起作用。 如果在文档中简单地说明了这一点,那将非常有帮助。

如果正确加载,每个都可以在表格中完美运行。 你是如何加载模板的?

@preichelt您应该从脚本标签中加载把手,以防止浏览器弄乱表格中的 {{#each}}。 您可以阅读有关堆栈溢出的更多信息:

http://stackoverflow.com/questions/15386276/why-should-we-wrap-our-templates-inside-script-blocks

这个错误浪费了我两个小时的生命,现在是周六晚上 10:30,我在我的办公室工作只是为了解决这个错误,直到我发现这个问题和 [Official Block Doc]
(http://handlebarsjs.com/builtin_helpers.html) 对此一无所知。

如果不清楚,这不是车把的错,而是不知道 HTML 是如何工作的: https: //html.spec.whatwg.org/multipage/syntax.html#an -introduction-to-error - 解析器中的处理和奇怪案例

那么,您认为尝试使用 Handlebarsjs 的每个人都应该对 HTML 解析器的工作原理有很好的了解? 如果不是,那么是_用户的错_,而不是文档清晰的错? 这个假设没有意义。 另一个沉重而复杂的模板引擎,Angularjs,使用Html兼容语法作为他们的模板语法,例如,如果我需要循环表,我可以使用

<tr ng-repeat="dto in tableData">

Angularjs 通过使用 Html 注释来保持循环的内部状态:

<!-- ngRepeat: column in row -->
<tr ng-repeat="dto in tableData">

Angualrjs 尝试尽可能尊重和遵循 Html 的语法,并成功避免假设。 但是 Handlebarsjs 的模板语法并没有,所以它向用户暴露了 Html 解析器问题。
如果您的开发人员无法解决您身边的问题,那么如果您真的关心您的项目和来自世界各地的用户,您就有责任告诉您的用户意识到这个问题。
无论如何,我将打开一个文档问题,因为_我相信我不是第一个遇到这个令人头疼的问题的人,也不会是最后一个。 _

Angular 在 DOM 中运行,所以它是 DOM 感知的。 Handlebars 只处理字符串,没有 DOM 的概念。

@profullstack :正如@stevenvachon所说,Handlebars 不适用于 HTML,而只能用于文本。 但这从文档中可能并不明显,因为所有示例都是 HTML。 它个人也使用它来生成降价...

如果您能告诉我,您在文档中需要什么样的文本,我很乐意添加它。 但是,一般使用说明(包括带有<script> -tag 的部分已经在http://handlebarsjs.com/ 的主页上

@profullstack我知道你对“浪费时间”感到沮丧,但在我看来,你完全倒退了。

没有任何开源项目或贡献者对您负有任何责任。 像把手这样的工具是免费创建和维护的,几乎不需要感谢,试图让其他开发人员的生活更轻松。 如果您无法使用任何开源项目,那么您的工作需要多长时间?

我可以直接告诉你,以这样的语气来写评论会与预期的效果相反。 简单的胡萝卜与大棒,如果您希望有人为您做某事,请很好地提出要求,甚至更好地提出 PR 并自己做。

@ErisDS谢谢你的建议。 也许我的第一条评论太强烈了,但我完全同意你的说法:

to try to making other developers lives easier

为什么我放弃 Angularjs 来使用 Handlebarsjs? _因为我相信 Handlebarsjs 会让我的生活比 Angularjs 更轻松。_
那么,请在文档中添加一些注意事项,以帮助您的数千名开源用户避免潜在的问题,这违背了您“让其他开发人员生活更轻松”的意愿? 我想不是。
为了:

No open source project nor contributor has any duty to you.

对,是真的。 你可以开始一个开源项目然后放弃它,这完全可以。 但是当你的项目成长时,你会花更多的时间和精力在你的项目上,你更喜欢你的项目,你也想与世界分享。 这时候你会开始_关心你的用户_和_关心你的文档_。 Handlebarsjs 就在这个阶段,这不是一个小项目,它是一个流行的项目,被全世界的程序员使用,甚至在韩国,在中国等等。
据我所知,Github 上的大多数开源程序员都为他们的项目和他们的 README.md 文件感到自豪,并希望越来越多的人使用他们的工具和代码。
因此,如果:

  • 你不想关心你的开源用户
  • 我是最后一个遇到这个问题的人
    您可以完全忽略我在第一条评论中的技术分析和此评论中的友好讨论。
    此外,开源项目不是你给世界的_慈善_,它是你和其他程序员之间的_沟通桥梁_。

@nknapp感谢您的回复。
也许我的第一条评论太强烈了,我为此和阅读我评论的人道歉。
乍一看,Handlebars 的工作原理就像_一个文本替换工具_,而且非常容易理解。 所以当我写这样的东西时:

{{#each myListData}}
                        <tr>{{name}}</tr>
{{/each}}

如果它只是简单的替换,我希望是这样的:

<tr>nameA</tr>
<tr>nameB</tr>

但是当遇到 HTML 时,它的行为有所不同,这是因为正如@stevenvachon亲切地指出的那样,这是因为 HTML 解析器的
所以我想在“每个块助手”部分下面只有一句话就足够了:

WARNING: please use script block when you try to use #each block inside table, due to the know issue of [How HTML parse works(thanks for <strong i="18">@stevenvachon</strong>'s reference](https://html.spec.whatwg.org/multipage/syntax.html#an-introduction-to-error-handling-and-strange-cases-in-the-parser)

如果你能分享你的意见,我真的很感激。 谢谢。

问题是,这与#each -helper 无关。 您永远不应该将模板直接写入 HTML。 像这样的声明应该在主页面上,但问题是:你会在那里读到吗?

也许我们可以在登录页面上的示例下方发出像您一样的警告...

只是另一个注意事项:

我不会在生产中使用脚本块方法。 相反,我会使用 Webpack 或其他工具来预编译模板。

@nknapp是的,我想您的意见是对的:我们永远不应该将模板直接写入 HTML。 所以我想在登陆页面上,第一个“入门”部分应该使用脚本作为示例,在下面的灰色块中,我们可以更改

You **can** deliver a template to the browser by including it in a <script> tag.

You **should always** deliver a template to the browser by including it in a <script> tag.

我猜你的建议是:

**never** write a template directly into HTML

完全正确,应该放在登陆页面让大家关注这个,这样可以避免很多问题。 我想这是个好主意,你认为是吗?

但是,这种解释不起作用,因为他们可能会将其理解为:

<script type="text/x-handlebars">
  {{#each list as |item|}}
    <td>{{item}}</td>
  {{/each}}
</script>

@stevenvachon是的,在您的示例中,仅将模板放入脚本中是不够的,也许我们需要添加更多有关使用模板的正确方法的注释,我们想听听您对此的建议。

也许:

对于大多数生产应用程序,您不会想要使用解析器和字符串模板。 查看预编译。

@stevenvachon感谢您的评论,我想如果我们将您的 HTML 解析器链接与您的评论放在一起会更好:

对于大多数生产应用程序,您不会想要使用解析器和字符串模板。 查看预编译。 如果您将模板直接用于 HTML,则存在一些已知问题,例如,由于HTML 解析器的工作方式,#each 块助手将无法在表格内

应该可以拆分成

  1. 直接在<script> -tag 示例下方

将模板放在<script> -tag 中很重要。 不要将它直接放入 HTML 中,否则 HTML 解析器可能会修改它(例如,如果它包含一个 table

  1. 将关于预编译的要点更改为。

请注意,不建议将此方法用于生产应用程序。 也可以预编译您的模板。 [...]

实际上,我个人不会再在浏览器中使用 Handlebars:还有许多其他框架(不仅是 Angular 和 React,还有 Vue 和 Ractive)。 这个视频很酷,并显示了问题...

我在服务器上使用 Handlebars 作为静态页面生成器,但对于浏览器渲染,我认为有更好的方法。

@nknapp我开始编写handlebars-html-parser用于通过 VDOM 将它带到浏览器,但它遇到了阻力

@nknapp感谢您的回复。 您的意见包括:

  1. 将模板放在一个内部的重要性

@profullstack我不是这个项目的维护者。

我已经进行了更改。

@nknapp谢谢,我相信很多人会从你的改变中受益。

我知道这个问题已经很老了,但由于 Sendgrid 的电子邮件模板编辑器没有遵循这些最佳实践,我最近遇到了这个问题。 如果其他人因为这个原因从 Google 解决了这个问题,一个解决方法是将把手代码放在 HTML 注释中。

<table >
  <tbody>
    <!-- {{#each items}} -->
    <tr>
      <td>{{this.key}}</td>
      <td>{{this.value}}</td>
    </tr>
    <!-- {{/each}} -->
  </tbody>
</table>

产生以下输出

<table>
  <tbody>
    <!--  -->
    <tr>
      <td>my key</td>
      <td>my value</td>
    </tr>
    <!--  -->
    <!--  -->
    <tr>
      <td>my key 2</td>
      <td>my value 2</td>
    </tr>
    <!--  -->
  </tbody>
<table>

(注意:我没有直接用 Handlebars 验证过,只是在 Sendgrid 的模板编辑器上)

谢谢@gurpreetatwal 的提示。 你用 SendGrid 的那个花絮为我节省了今晚调试的时间!

@gurpreetatwal但为什么呢?

@Lazarencjusz为什么关于修复工作的原因或为什么 SendGrid 电子邮件模板编辑器无法正常工作?

你好! 当您使用 div 元素而不是表格时,将起作用。
还将所有表格元素重写为 div。

@gurpreetatwal的解决方案适用于我的 Mailchimp/Mandrills 车把模板。 谢谢你帮我省了很多麻烦!

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

nknapp picture nknapp  ·  3评论

novwhisky picture novwhisky  ·  4评论

ShintaroOkuda picture ShintaroOkuda  ·  7评论

DylanPiercey picture DylanPiercey  ·  7评论

snimavat picture snimavat  ·  5评论