把手不填表

时间:2013-12-16 14:32:52

标签: javascript jquery backbone.js handlebars.js

我正在使用Handlebars(v 1.0.0)来填充HTML表格。 但不知怎的,它并没有像我以前那样填满表格。

这是我的模板:

{{#if users}}
<table>
    {{#each users}}
        <tr>
            <td>{{username}}</td>
            <td>{{email}}</td>
        </tr>
    {{/each}}
</table>

{{else}}
    <h3>No users found!</h3>
{{/if}}

所以我确实找到了用户,因为我没有看到“找不到用户!”当我调用一个空对象时,它确实显示“找不到用户!”。

当我不使用该表并打印出这些用户时,如下一个示例。用户名和邮件地址'将显示在我的HTML中。

{{#if users}}

    {{#each users}}

        {{username}}<br/>
        {{email}}<br/>

    {{/each}}


{{else}}
    <h3>No users found!</h3>
{{/if}}

以下是我在javascript中构建模板的方法:

var htmlSource = $(data).html();
var template = Handlebars.compile(htmlSource);
var compiled = template(usersArray);
that.$el.html(compiled);

现在当我在console.log中编译对象时,它不会显示该表。

你知道为什么它不起作用你可以帮助我吗?

编辑:

我刚刚测试了一些,发现当我省略<table>标签时,数据会显示在HTML中。但是,<tr><td>不会显示在html中。将显示其中的数据。

编辑2: 我发现它似乎是一个jquery问题或javascript问题。 当我在console.log中将htmlSource的HTML模板更改为:

{{#if users}}

    {{#each users}}

    {{/each}}


{{else}}
<h3>No users found!</h3>
{{/if}}

<table><tr>
   <td>{{username}}</td> 
   <td>{{email}}</td>
</tr></table>

如您所见,表格移到了if语句之外。 我尝试了其他jquery版本(2.0.2,2.0.3,2.0.1,1.10.2),但这不起作用。 我尝试使用innerXHTML脚本,但这与jQuery的工作方式相同。

所以我的猜测是它可能是一个FireFox问题(尽管我试过25和26),Chrome做同样的事情......也许是EcmaScript中的东西?

我会尽快通知你......

编辑3:

我用我需要的html创建了一个html文件。使用脚本我得到我需要的html的特定部分并将其放在数据变量中。

现在,当控制台记录数据(console.log(数据))时,没有任何错误。 当控制台使用jQuery记录数据时,html会被更改:console.log($(data));

似乎出现了问题......但仅限于使用表格标签时。 这是jQuery无法处理的东西吗?我不知道。我知道如何通过使用脚本标记来解决这个问题...虽然我想使用require加载它;)

P.S。 nemesv谢谢你的编辑;)

2 个答案:

答案 0 :(得分:15)

确保您在标记中输出模板,以便浏览器不会尝试解析它。

<script type="x-template" id="the-tpl">
    {{#if users}}
        <table>
            {{#each users}}
                <tr>
                    <td>{{username}}</td>
                    <td>{{email}}</td>
                </tr>
            {{/each}}
        </table>
    {{else}}
        <h3>No users found!</h3>
    {{/if}}
</script>

如果脚本标记上没有type属性,HTML解析器将找到错误并尝试解决它。根据您的错误详细信息,这看起来确实如此。

使用require

正如您所说,使用“需求”加载,而不是确保使用text! plugin加载模板:require("text!path/to/template.html")

为了更加漂亮,你可以将所有把手编译委托给handlebars template loading plugin,这样模板就会在你的构建中进行预编译 - 这可能是最好的。

无论哪种方式,您的问题是HTML解析器会解析您的模板,这会破坏您的模板内容。确保通过XMLHttpRequest将其加载为“text”,或者使用require或在正确键入的脚本标记内加载。

答案 1 :(得分:0)

Simon的解决方案是正确的,并且在各种评论中讨论了问题。 我只是把碎片放在这里。

正如@rescuecreative指出,当在DOM中插入html时,某些浏览器会删除空的<table>标记。

这里的情况有点类似。浏览器在看到无效标记时会出现行为异常。但在这种情况下,它不是因为缺少tr,td在表内。因为表格中的tr之前有额外的行。

你的问题从这里开始。

var htmlSource = $(data).html();

无论您使用何种加载机制,都可以在使用把手编译模板之前将模板插入DOM中。

将未编译的模板添加到DOM时会发生这种情况。

{{#if users}}  <!-- browser does not understand this and tries to print it as it is-->
<table>  <!-- browser sees the table tag and immediately looks for child TR, tbody, thead -->
    {{#each users}}  <!-- but instead finds plain text and hence considers it as invalid markup -->
        <tr>   <!-- the same story is repeated again>
            <td>{{username}}</td>
            <td>{{email}}</td>
        </tr>
    {{/each}}  <!-- such plain strings are taken out of table markup and placed before or after depending upon the browser, in case of chrome placed before the table -->
</table>

{{else}}
    <h3>No users found!</h3>
{{/if}}

这就是chrome渲染它的方式 -

{{#if users}}
{{#each users}}
{{/each}}
<table>
    <tbody>
        <tr>
            <td>{{username}}</td>
            <td>{{email}}</td>
        </tr>
    </tbody>
</table>
{{else}}
    <h3>No users found!</h3>
{{/if}}

到目前为止,我还没有和我一起使用Firefox。但我相信firefox有自己的标记修正方法。

之后,当你使用jquery和编译

将它从DOM中取出时
var htmlSource = $(data).html();
var template = Handlebars.compile(htmlSource);

它只会输出这个

<table>
    <tbody>
        <tr>
            <td>{{username}}</td>
            <td>{{email}}</td>
        </tr>
    </tbody>
</table>

如果你想要你可以在编译之后将其转储以查看。

var compiled = template(usersArray);
console.log(compiled);
that.$el.html(compiled);

这也解释了当您在原始模板中删除表格标记时获取用户名和电子邮件的原因。

现在解决这个问题要么像Simon指出的那样使用text plugin。或将模板内联。

我也使用requriejs以及下面的内容

define([
  'underscore',   // you can replace this with handlebars
  'text!path/to/template.html'
], function(_, Tmpl){
  return _.template(Tmpl);  //and handlebar pre-compilation here
});

这样您也可以在构建过程中使用预编译的模板替换此模块。