如果数组包含 Eleventy 的另一个数组值,如何检查 Nunjucks

问题描述

所以我有一些来自 JSON API 的书籍数据。对于 API 中的一些项目,我在 11ty 中创建了一个页面。我正在尝试从 API 中列出项目,并检查每个项目的 slug 字段是否与我的本地页面集合中的 fileSlug 匹配。如果是这样,那么我可以输出内容页面的链接;否则,只需从 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 中没有相应页面的项目,它返回 {{1} }.对于有相应页面的项目,它返回 Item only exists on API. Item only exists on API.

知道为什么 Item exists locally. Item only exists on API. 语句总是返回 true 吗?


else 中创建自定义过滤器:

.eleventy.js

解决方法

问题是嵌套循环。您有一个 API 书籍循环,另一个循环用于每一本本地书籍,因此您的代码针对 API 中的每一本书运行所有本地书籍。这就是您看到额外输出的原因,总行数将是 API 图书的数量乘以本地图书的数量(例如 2 * 2 = 42 * 3 = 6)。

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

相反,我建议将您的逻辑移至 JavaScript,在那里您可以使用 Array.prototype.find 和类似方法更轻松地进行比较。例如,您的 apiBooks 变量是否来自数据文件?在这种情况下,您可以在那里解析列表并添加对本地图书文件的引用(如果可用)。另一种方法是添加一个 custom filter,它将一个 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 %}