Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Динамические маршруты

Динамический маршрут — страница, у которой часть адреса меняется: /posts/first-post, /posts/learning-astro. Параметр пишут в имени файла в квадратных скобках. Поскольку статический сайт собирается заранее, Astro должен знать все возможные значения параметра — их возвращает функция getStaticPaths().

Страница статьи

Удалите src/pages/posts/first-post.astro и создайте src/pages/posts/[id].astro:

---
import { getCollection, render } from 'astro:content';
import BaseLayout from '../../layouts/BaseLayout.astro';
 
export async function getStaticPaths() {
  const posts = await getCollection('blog');
  return posts.map((post) => ({
    params: { id: post.id },
    props: { post },
  }));
}
 
const { post } = Astro.props;
const { Content } = await render(post);
---
 
<BaseLayout title={post.data.title}>
  <h1>{post.data.title}</h1>
  <p>{post.data.pubDate.toLocaleDateString('ru-RU')}</p>
  <Content />
</BaseLayout>

Откройте /posts/first-post и /posts/learning-astro — обе страницы собраны из одного файла. Ссылки на них уже есть в списке /posts.

Как это работает

getStaticPaths() возвращает массив объектов, по одному на страницу:

ПолеЧто в нём
paramsЗначения параметров адреса: { id: 'first-post' } даёт /posts/first-post
propsДанные, которые страница получит в Astro.props

Значения параметров доступны и в Astro.params, например Astro.params.id. При сборке Astro вызовет функцию один раз и создаст по HTML-файлу на каждый элемент массива.

Страница тега

Тот же приём делает страницы тегов. Создайте src/pages/tags/[tag].astro:

---
import { getCollection } from 'astro:content';
import BaseLayout from '../../layouts/BaseLayout.astro';
import PostCard from '../../components/PostCard.astro';
 
export async function getStaticPaths() {
  const posts = await getCollection('blog');
  const tags = [...new Set(posts.flatMap((post) => post.data.tags))];
 
  return tags.map((tag) => ({
    params: { tag },
    props: { posts: posts.filter((post) => post.data.tags.includes(tag)) },
  }));
}
 
const { tag } = Astro.params;
const { posts } = Astro.props;
---
 
<BaseLayout title={`Тег ${tag}`}>
  <h1>Статьи с тегом «{tag}»</h1>
  {posts.map((post) => <PostCard title={post.data.title} url={`/posts/${post.id}`} />)}
</BaseLayout>

Set убирает повторы, и для каждого тега получается своя страница. Откройте /tags/astro — там будут только статьи с тегом astro. Ссылку на тег можно вывести в статье: <a href={'/tags/' + tag}>.

Несколько сегментов

Параметр с тремя точками, [...slug].astro, захватывает адрес любой глубины: /docs/a/b/c. Он нужен, когда записи лежат во вложенных папках.

Частая ошибка

В params кладут значение, которое не совпадает с ссылками на сайте, например заголовок статьи с пробелами вместо id. Страница собирается по одному адресу, а ссылки ведут на другой, и посетитель видит 404. Берите для адреса одно и то же поле — post.id — и в getStaticPaths(), и в ссылках.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.