5. Лейауты
Макеты (Layouts) в Astro — это специальные компоненты, предназначенные для оборачивания страниц общей структурой. Вместо того чтобы повторять <html>, <head>, навигацию и футер на каждой странице, вы выносите их в макет и переиспользуете.
Зачем нужны макеты
Заголовок раздела «Зачем нужны макеты»Без макетов каждая страница содержала бы дублирование:
---// src/pages/about.astro — БЕЗ макета (плохой подход)---<html lang="ru"> <head> <meta charset="UTF-8" /> <title>О нас</title> <link rel="stylesheet" href="/styles/global.css" /> </head> <body> <nav><!-- повторяется на каждой странице --></nav> <main> <h1>О нас</h1> </main> <footer><!-- повторяется на каждой странице --></footer> </body></html>С макетами структура разделяется правильно.
Создание макета
Заголовок раздела «Создание макета»---interface Props { title: string; description?: string;}
const { title, description = 'Мой Astro сайт' } = Astro.props;---
<html lang="ru"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width" /> <meta name="description" content={description} /> <title>{title} | Мой сайт</title> <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> </head> <body> <nav> <a href="/">Главная</a> <a href="/blog">Блог</a> <a href="/about">О нас</a> </nav>
<main> <slot /> <!-- Сюда вставится контент страницы --> </main>
<footer> <p>© 2024 Мой сайт</p> </footer> </body></html>Использование макета
Заголовок раздела «Использование макета»---import BaseLayout from '../layouts/BaseLayout.astro';---
<BaseLayout title="О нас" description="Информация о нашей команде"> <h1>О нас</h1> <p>Мы создаём крутые сайты на Astro!</p></BaseLayout>Весь контент между тегами <BaseLayout> попадёт в <slot /> макета.
Именованные слоты
Заголовок раздела «Именованные слоты»Один <slot /> — это хорошо, но иногда нужно несколько областей для контента:
---import BaseLayout from './BaseLayout.astro';
const { title, author, date } = Astro.props;---
<BaseLayout title={title}> <article> <header> <h1>{title}</h1> <div class="meta"> <slot name="author-info" /> <!-- Именованный слот для автора --> </div> </header>
<div class="content"> <slot /> <!-- Основной контент статьи --> </div>
<aside> <slot name="sidebar" /> <!-- Слот для боковой панели --> </aside> </article></BaseLayout>---import BlogLayout from '../../layouts/BlogLayout.astro';---
<BlogLayout title="Моя статья"> <!-- Контент для slot name="author-info" --> <div slot="author-info"> <img src="/avatar.jpg" alt="Автор" /> <span>Алексей Иванов</span> </div>
<!-- Основной контент (дефолтный slot) --> <p>Это основной текст статьи...</p> <p>Продолжение...</p>
<!-- Контент для slot name="sidebar" --> <nav slot="sidebar"> <h3>Содержание</h3> <ul> <li><a href="#intro">Введение</a></li> <li><a href="#main">Основная часть</a></li> </ul> </nav></BlogLayout>Вложенные макеты
Заголовок раздела «Вложенные макеты»Макеты могут быть вложены друг в друга — это типичный паттерн:
BaseLayout.astro└── BlogLayout.astro └── PostLayout.astro └── post.astro (страница)---import BlogLayout from './BlogLayout.astro';
interface Props { title: string; pubDate: Date; tags: string[];}
const { title, pubDate, tags } = Astro.props;---
<BlogLayout title={title}> <div slot="author-info"> <time>{pubDate.toLocaleDateString('ru-RU')}</time> {tags.map(tag => <span class="tag">#{tag}</span>)} </div>
<slot /> <!-- Контент конкретной статьи --></BlogLayout>Макеты для Markdown страниц
Заголовок раздела «Макеты для Markdown страниц»Markdown-страницы могут использовать макеты через frontmatter:
---layout: ../../layouts/PostLayout.astrotitle: 'Введение в Astro'pubDate: 2024-01-15tags: ['astro', 'webdev', 'javascript']---
# Введение в Astro
Этот контент будет вставлен в `<slot />` PostLayout.В Astro 3+, для MDX используйте import:
import PostLayout from '../../layouts/PostLayout.astro'
export const frontmatter = { title: 'Введение в Astro', pubDate: new Date('2024-01-15'),}
<PostLayout {...frontmatter}> # Введение в Astro
Контент MDX страницы...</PostLayout>Передача данных через макеты
Заголовок раздела «Передача данных через макеты»Макеты могут принимать пропсы от Markdown через Astro.props.frontmatter:
---const { frontmatter } = Astro.props;// frontmatter содержит все данные из YAML frontmatter markdown-файлаconst { title, author, tags } = frontmatter;---
<html> <head><title>{title}</title></head> <body> <h1>{title}</h1> <p>Автор: {author}</p> <slot /> </body></html>Интерактивный конструктор макетов
Заголовок раздела «Интерактивный конструктор макетов»Посмотрите как контент проходит через вложенные макеты: