0

所以我有一些来自 JSON API 的书籍数据。对于API中的一些项目,我在11ty创建了一个页面。我正在尝试列出 API 中的项目,并检查每个项目的slug字段是否与fileSlug我的本地页面集合中的 a 匹配。如果是这样,那么我可以输出到内容页面的链接;否则,只需从 API 输出书名。

这是我在 Nunjucks 中所拥有的:

{# Loop through book entries in API #}
{% for apiBook in booksApi %}
  {{ apiBook.title }}: 
  {# Loop through my local book pages collection #}
  {% for localBook in collections.books %}
    {# Check if any slugs in the local collection match slugs in API #}
    {% if localBook.fileSlug == apiBook.slug %}
      Item exists locally.
    {% else %}
      Item only exists on API.
    {% endif %}
  {% endfor %}
  <br>
{% endfor %}

我不明白的是,这对于 API 中的每个项目都会返回两次......对于 11ty 中没有相应页面的项目,它会返回Item only exists on API. Item only exists on API.. 对于确实有相应页面的项目,它返回Item exists locally. Item only exists on API..

任何想法为什么它总是为else声明返回 true?


在中创建自定义过滤器.eleventy.js

eleventyConfig.addFilter("matchLocalBook", (apiBook, localBooks) => {
  return localBooks.find(element => element.fileSlug === apiBook.slug);
});
4

1 回答 1

1

问题是嵌套循环。API 书籍有一个循环,每本本地书籍都有一个循环,因此您的代码在 API 中的每一本书的所有本地书籍中运行。这就是为什么您会看到额外的输出,总行数将是 API 书籍的数量乘以本地书籍的数量(例如2 * 2 = 4,或2 * 3 = 6)。

在 Nunjucks 中,您想做的事情并非微不足道。通常,您可以使用in关键字来检查一本书是否属于您的收藏,但是当您需要比较对象属性时,这不起作用。

相反,我建议将您的逻辑转移到 JavaScript,在那里您可以使用Array.prototype.find和类似方法更轻松地进行比较。例如,您的 apiBooks 变量是否来自数据文件?在这种情况下,您可以在那里解析列表并添加对本地书籍文件的引用(如果可用)。另一种方法是添加一个自定义过滤器,该过滤器将 apiBook 对象和本地书籍集合作为参数并返回匹配的书籍(如果存在)。

// .eleventy.js
eleventyConfig.addFilter('getLocalBook', (bookData, localBooks) => {
    // find matching book and return it, or return null
} );

然后你可以像这样使用它:

{% for apiBook in booksApi %}
  {% set localBook = apiBook | getLocalBook(collections.books) %}
  {% if localBook %}
    Item exists locally.
  {% else %}
    Item only exists on API.
  {% endif %}
{% endfor %}
于 2021-01-04T15:57:00.993 回答