【问题标题】:Handlebars nested 'each' syntax - not iterating over each element车把嵌套“每个”语法 - 不迭代每个元素
【发布时间】:2013-06-16 08:53:56
【问题描述】:

我在 Javascript/JSON/Handlebars 方面是全新的,我在获取具有两个嵌套级别的 JSON 对象以在 Handlebars 模板中工作时遇到问题。

我已经用 JSONLint 验证了 JSON 对象,所以它是有效的 JSON 代码,但我不知道我是否有正确的 JSON 格式来使模板正常工作。 :) (我在另一个系统中手动构建 JSON。)或者可能是我不正确的模板语法。这就是我希望找到的...

简短描述:这个对象是一个目录。我有章节,然后是每个章节中的电影。所以电影是每个章节元素的嵌套元素。

我想要类似于以下内容的 HTML 输出:

Chapter1:  ChapterName
       Movie1: MovieName
       Movie2: MovieName
Chapter2:  Chaptername
       Movie1: MovieName
       Movie2: MovieName
       Movie3: MovieName

我似乎只得到了 1 个数据实例(我的 JSON 对象中的最后一个元素),或者我什么也得不到。 (取决于我尝试的小调整或版本。)浏览器控制台不显示任何错误。

这是我目前尝试使用的所有代码(脚本、HTML、模板等):

<!DOCTYPE html>
<html>
<head>  <meta charset="UTF-8">
    <title>Handlebars Demo</title>
    <!-- dependant files -->
    <script src="Handlebars.js"></script>
</head>

<!-- template -->
<script id="template2" type="text/x-handlebars-template">
    <div>Chapter stuff:</div>
    <ul>{{#each Chapter}}
        <ol>{{@index}} {{ChapterName}}
        {{#each movies}}
            <li>Movie ID:{{movieIDnum}}</li>
        {{/each}}
        </ol>
        {{/each}}
    </ul>
</script>


<body><div id="main"></div></body>

<script>
    var source = document.getElementById('template2').innerHTML;
    var template = Handlebars.compile(source);
    var data = {
        "Chapter" : {
                "ChapterName" : "Introduction",
                "chapterNum" : "1",
                "movies" : [
                        {
                        "movieIDnum" : "16244028",
                        "movieName" : "Update Test Movie 0",
                        "movieFileName" : "Test0.mov",
                        "moviePositionInChapter" : "1"
                        }
                ]
        },

        "Chapter" : {
            "ChapterName" : "Welcome",
            "chapterNum" : "2",
            "movies" : [
                    {
                    "movieIDnum" : " 17322365",
                    "movieName" : "Update Test movie 1",
                    "movieFileName" : "Test1.mov",
                    "moviePositionInChapter" : "1"
                    },
                    {
                    "movieIDnum" : " 17326267",
                    "movieName" : "Update Test movie 3",
                    "movieFileName" : "Test3.mov",
                    "moviePositionInChapter" : "2"
                    }
            ]
        },

        "Chapter" : {
            "ChapterName" : "The new Interface",
            "chapterNum" : "2",
            "movies" : [
                {
                "movieIDnum" : " 1732123476",
                "movieName" : "Update Test movie 12",
                "movieFileName" : "Test12.mov",
                "moviePositionInChapter" : "1"
                },
                {
                "movieIDnum" : " 173262373",
                "movieName" : "Update Test movie 9",
                "movieFileName" : "Test9.mov",
                "moviePositionInChapter" : "2"
                },
                {
                "movieIDnum" : " 173273474",
                "movieName" : "Update Test movie 10",
                "movieFileName" : "Test10.mov",
                "moviePositionInChapter" : "3"
                }
            ]
        },

        "Chapter" : {
            "ChapterName" : "What is an Update?",
            "chapterNum" : "4",
            "movies" : [
                {
                "movieIDnum" : " 177342131",
                "chapterNum" : "4",
                "chapterName" : "What is an Update?",
                "movieName" : "Test movie again",
                "movieFileName" : "Test13.mov",
                "moviePositionInChapter" : "1"
                }
                ]
                },
        "Chapter" : {
            "ChapterName" : "Editing",
            "chapterNum" : "5",
            "movies" : [
                {
                "movieIDnum" : " 173290878",
                "movieName" : "Update Test movie 14",
                "movieFileName" : "Test14mov",
                "moviePositionInChapter" : "1"
                },
                {
                "movieIDnum" : " 177344914",
                "movieName" : " Movie 15 Test",
                "movieFileName" : "Test233.mov",
                "moviePositionInChapter" : "2"
                }
            ]
        }

    }

    var result = template(data);
    document.write(result);

</script>
</html>

我想知道为什么这不起作用,而不仅仅是“以下是如何使用 4 种完全不同格式的其他不同事物来解决您的问题”。据我了解,这应该可以与我尝试使用的工具一起使用。我想更好地了解这些工具并从过程中学习,而不仅仅是获得解决方案。 (你知道,教人钓鱼……:))

谢谢, J

【问题讨论】:

    标签: json nested each handlebars.js


    【解决方案1】:

    建议进行一些更改,首先您不应该编写具有多个键的对象{ Chapter:, Chapter:, etc...}

    另一个建议是检查 Handlebars 的工作方式,它并不需要在每种情况下都使用。希望它澄清。

    试试这些改变:

    <!DOCTYPE html>
    <html>
    <head>  <meta charset="UTF-8">
        <title>Handlebars Demo</title>
        <!-- dependant files -->
        <script src="handlebars.js"></script>
    </head>
    
    <!-- template -->
    <script id="template2" type="text/x-handlebars-template">
        <div>Chapter stuff:</div>
        <ul>{{#Chapters}}
            <ol>{{@index}} {{ChapterName}}
            {{#movies}}
                <li>Movie ID:{{movieIDnum}}</li>
            {{/movies}}
            </ol>
            {{/Chapters}}
        </ul>
    </script>
    
    
    <body><div id="main"></div></body>
    
    <script>
        var source = document.getElementById('template2').innerHTML;
        var template = Handlebars.compile(source);
        var data = [
            {
                    "ChapterName" : "Introduction",
                    "chapterNum" : "1",
                    "movies" : [
                            {
                            "movieIDnum" : "16244028",
                            "movieName" : "Update Test Movie 0",
                            "movieFileName" : "Test0.mov",
                            "moviePositionInChapter" : "1"
                            }
                    ]
            },
            {
                "ChapterName" : "Welcome",
                "chapterNum" : "2",
                "movies" : [
                        {
                        "movieIDnum" : " 17322365",
                        "movieName" : "Update Test movie 1",
                        "movieFileName" : "Test1.mov",
                        "moviePositionInChapter" : "1"
                        },
                        {
                        "movieIDnum" : " 17326267",
                        "movieName" : "Update Test movie 3",
                        "movieFileName" : "Test3.mov",
                        "moviePositionInChapter" : "2"
                        }
                ]
            },
            {
                "ChapterName" : "The new Interface",
                "chapterNum" : "2",
                "movies" : [
                    {
                    "movieIDnum" : " 1732123476",
                    "movieName" : "Update Test movie 12",
                    "movieFileName" : "Test12.mov",
                    "moviePositionInChapter" : "1"
                    },
                    {
                    "movieIDnum" : " 173262373",
                    "movieName" : "Update Test movie 9",
                    "movieFileName" : "Test9.mov",
                    "moviePositionInChapter" : "2"
                    },
                    {
                    "movieIDnum" : " 173273474",
                    "movieName" : "Update Test movie 10",
                    "movieFileName" : "Test10.mov",
                    "moviePositionInChapter" : "3"
                    }
                ]
            },
            {
                "ChapterName" : "What is an Update?",
                "chapterNum" : "4",
                "movies" : [
                    {
                    "movieIDnum" : " 177342131",
                    "chapterNum" : "4",
                    "chapterName" : "What is an Update?",
                    "movieName" : "Test movie again",
                    "movieFileName" : "Test13.mov",
                    "moviePositionInChapter" : "1"
                    }
                    ]
            },
            {
                "ChapterName" : "Editing",
                "chapterNum" : "5",
                "movies" : [
                    {
                    "movieIDnum" : " 173290878",
                    "movieName" : "Update Test movie 14",
                    "movieFileName" : "Test14mov",
                    "moviePositionInChapter" : "1"
                    },
                    {
                    "movieIDnum" : " 177344914",
                    "movieName" : " Movie 15 Test",
                    "movieFileName" : "Test233.mov",
                    "moviePositionInChapter" : "2"
                    }
                ]
            }
        ];
    
        var result = template({Chapters: data});
        document.write(result);
    
    </script>
    </html>
    

    【讨论】:

    • 您能澄清一下 Handlebars“没有每个”的意思吗? handlebarsjs.com/#iteration
    • 应该说需要,感谢您的澄清。我通常更喜欢使用#collection 而不是迭代器。
    • 哦,是的,这很有道理。
    • 啊,有道理。我认为我已经将“章节”对象扔在那里,以便为“每个”功能提供一些可以抓住的东西。 IE。 “对于每个标记为‘章节’的对象……”。按照您的建议删除了相同标签的东西,并修改了我的模板,它现在可以工作了。谢谢!
    • 不应该'首先你不应该写一个有多个键的对象'是'首先你不应该写一个有几个相同键的对象'?
    【解决方案2】:

    pdjota 是正确的。这个答案只是为了展示如何根据需要使用 each 块助手。

    就像 pdjota 明智地指出的那样,您正在覆盖对象的元素,因为它们都具有相同的键,即“章节”。所以把data变成一个对象数组,而不是一个拥有相同键的对象的对象。

    如果你这样做,你仍然可以将data 传递给template()。您缺少的是如何引用每个块中使用的对象的属性。这是通过this 完成的。例如,如果您在 movies 迭代器中,则 movies 对象的属性引用如下:this.movieIDnumthis.movieName 等。

    <!DOCTYPE html>
    <html>
    <head>  
        <meta charset="UTF-8">
        <title>Handlebars Demo</title>
        <!-- dependant files -->
        <script src="Handlebars.js"></script>
    </head>
    
    <!-- template -->
    <script id="template2" type="text/x-handlebars-template">
        <div>Chapter stuff:</div>
        <ul>
            {{#each this}}
                <ol>Chapter{{this.chapterNum}}: {{this.ChapterName}}
                    {{#each movies}}
                        <li>Movie{{this.moviePositionInChapter}}: {{this.movieName}}</li>
                    {{/each}}
                </ol>
            {{/each}}
        </ul>
    </script>
    
    
    <body><div id="main"></div></body>
    
    <script>
        var source = document.getElementById('template2').innerHTML;
        var template = Handlebars.compile(source);
        var data = [
            {
                    "ChapterName" : "Introduction",
                    "chapterNum" : "1",
                    "movies" : [
                            {
                            "movieIDnum" : "16244028",
                            "movieName" : "Update Test Movie 0",
                            "movieFileName" : "Test0.mov",
                            "moviePositionInChapter" : "1"
                            }
                    ]
            },
            {
                "ChapterName" : "Welcome",
                "chapterNum" : "2",
                "movies" : [
                        {
                        "movieIDnum" : " 17322365",
                        "movieName" : "Update Test movie 1",
                        "movieFileName" : "Test1.mov",
                        "moviePositionInChapter" : "1"
                        },
                        {
                        "movieIDnum" : " 17326267",
                        "movieName" : "Update Test movie 3",
                        "movieFileName" : "Test3.mov",
                        "moviePositionInChapter" : "2"
                        }
                ]
            },
            {
                "ChapterName" : "The new Interface",
                "chapterNum" : "2",
                "movies" : [
                    {
                    "movieIDnum" : " 1732123476",
                    "movieName" : "Update Test movie 12",
                    "movieFileName" : "Test12.mov",
                    "moviePositionInChapter" : "1"
                    },
                    {
                    "movieIDnum" : " 173262373",
                    "movieName" : "Update Test movie 9",
                    "movieFileName" : "Test9.mov",
                    "moviePositionInChapter" : "2"
                    },
                    {
                    "movieIDnum" : " 173273474",
                    "movieName" : "Update Test movie 10",
                    "movieFileName" : "Test10.mov",
                    "moviePositionInChapter" : "3"
                    }
                ]
            },
            {
                "ChapterName" : "What is an Update?",
                "chapterNum" : "4",
                "movies" : [
                    {
                    "movieIDnum" : " 177342131",
                    "chapterNum" : "4",
                    "chapterName" : "What is an Update?",
                    "movieName" : "Test movie again",
                    "movieFileName" : "Test13.mov",
                    "moviePositionInChapter" : "1"
                    }
                    ]
            },
            {
                "ChapterName" : "Editing",
                "chapterNum" : "5",
                "movies" : [
                    {
                    "movieIDnum" : " 173290878",
                    "movieName" : "Update Test movie 14",
                    "movieFileName" : "Test14mov",
                    "moviePositionInChapter" : "1"
                    },
                    {
                    "movieIDnum" : " 177344914",
                    "movieName" : " Movie 15 Test",
                    "movieFileName" : "Test233.mov",
                    "moviePositionInChapter" : "2"
                    }
                ]
            }
        ];
    
        var result = template(data);
        document.write(result);
    
    </script>
    </html>
    

    【讨论】:

    • 泰勒,感谢您的发帖。通读您和 PDJota 的回复,让我明白了一些事情。你的额外好处是解释了为什么我只获取我定义的最后一个元素的数据:每个元素都被下一个定义的元素覆盖。不过,Handlebars 肯定有一些默认效果,因为我能够在大多数情况下使用没有“This”的模板(请参阅下一条评论,即使它的格式不是很好):
      • {{#each this}}
          {{@index}} {{ChapterName}} {{#movies}}
        • {{@index}} + 1 {{moviePositionInChapter}} 电影 ID:{{movieIDnum}} 电影名称:{{movieName}} 文件名: {{movieFilename}}
        • {{/movies}}
        {{/each}}
  • 你回答得非常好,坚持我的要求找出这个方法。抱歉,由于我还没有代表,所以我不能给你答案道具。
  • 猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-12
    • 1970-01-01
    • 2017-08-04
    • 1970-01-01
    • 2020-03-22
    • 2013-02-05
    • 1970-01-01
    相关资源
    最近更新 更多