六维教程

Astro 列表渲染

基本渲染

用 map 渲染数组

把数组里的每一项变成 HTML 元素,最常用的是 map

---
const fruits = ['苹果', '香蕉', '橙子'];
---
<ul>
  {fruits.map((fruit) => <li>{fruit}</li>)}
</ul>

渲染结果:

<ul>
  <li>苹果</li>
  <li>香蕉</li>
  <li>橙子</li>
</ul>

渲染对象数组

实际项目里往往是对象数组,比如文章列表。

---
const posts = [
  { title: 'Astro 入门', href: '/blog/intro' },
  { title: 'Astro 路由', href: '/blog/routing' },
];
---
<ul>
  {posts.map((post) => (
    <li><a href={post.href}>{post.title}</a></li>
  ))}
</ul>

嵌套列表

map 里可以再套 map,渲染二维数据。

---
const groups = [
  { name: '水果', items: ['苹果', '梨'] },
  { name: '蔬菜', items: ['西红柿', '黄瓜'] },
];
---
{groups.map((g) => (
  <section>
    <h3>{g.name}</h3>
    <ul>{g.items.map((i) => <li>{i}</li>)}</ul>
  </section>
))}

注意事项

必须加 key 吗

在 Vue/React 里 map 要求加 key,但在 Astro 里没有这个硬性要求。

Astro 在构建阶段就把列表渲染成静态 HTML,不存在「后续重排比对」的问题,所以一般不用写 key

不过如果你混用了 React 等框架组件并在客户端渲染,那时才需要遵循对应框架的规则。

空数组的处理

当数组为空时,map 不会产生任何元素。你也可以给个友好提示。

---
const posts = [];
---
{posts.length === 0 ? (
  <p>还没有文章</p>
) : (
  <ul>{posts.map((p) => <li>{p.title}</li>)}</ul>
)}

配合内容集合

内容集合是 Astro 用来集中管理 Markdown 文章的机制,配置写在 src/content.config.ts 里;查出来的每条文章是一个条目对象,post.data 对应它的 front-matter 字段,post.id 是文件名(不含扩展名)。这块后面第 18 篇会专门讲,这里先借列表渲染看一下它长什么样。

列表渲染最常见的真实场景,就是从内容集合读取所有文章再列出,示例:

---
import { getCollection } from 'astro:content';
const posts = await getCollection('blog'); // 读取名为 blog 的内容集合,得到文章数组
---
  <!-- post.id 是文章文件名,post.data 是 front-matter 里的字段 -->
  <ul>
    {posts.map((post) => (
      <li><a href={`/blog/${post.id}`}>{post.data.title}</a></li>
    ))}
  </ul>
上一篇
Astro 条件渲染
下一篇
Astro 插槽 slot