Макеты
Макеты (layouts) — это компоненты Astro, предназначенные для создания переиспользуемой структуры интерфейса, например шаблона страницы.
Традиционно мы называем «макетами» компоненты, которые содержат общие элементы страниц: шапку, меню навигации и подвал. Типичный макет Astro предоставляет страницам (Astro, Markdown или MDX):
- оболочку страницы (теги
<html>,<head>и<body>); <slot />, определяющий место для вставки контента конкретной страницы.
При этом макеты — это обычные компоненты Astro! Они могут принимать пропсы, импортировать другие компоненты, использовать UI-фреймворки и скрипты. Они даже не обязательно должны содержать полную оболочку страницы и могут использоваться как частичные UI-шаблоны.
Однако, если макет всё же содержит оболочку страницы, тег <html> должен быть родителем для всех остальных элементов компонента.
Макеты принято размещать в папке src/layouts/, но это не обязательное требование — вы можете хранить их где угодно. Можно даже размещать их рядом со страницами, добавляя префикс _ к именам файлов, чтобы они не стали отдельными маршрутами.
Пример макета
Заголовок раздела «Пример макета»---import BaseHead from '../components/BaseHead.astro';import Footer from '../components/Footer.astro';const { title } = Astro.props;---<html lang="ru"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <BaseHead title={title}/> </head> <body> <nav> <a href="/">Главная</a> <a href="/posts">Посты</a> <a href="/contact">Контакты</a> </nav> <h1>{title}</h1> <article> <slot /> <!-- контент страницы попадет сюда --> </article> <Footer /> </body> <style> h1 { font-size: 2rem; } </style></html>Использование макета:
---import MySiteLayout from '../layouts/MySiteLayout.astro';---<MySiteLayout title="Главная страница"> <p>Контент моей страницы, обёрнутый в макет!</p></MySiteLayout>TypeScript в макетах
Заголовок раздела «TypeScript в макетах»Любой макет можно сделать типобезопасным, определив интерфейс для его пропсов:
---interface Props { title: string; description: string; publishDate: string; viewCount: number;}const { title, description, publishDate, viewCount } = Astro.props;---<html lang="ru"> <head> <meta charset="UTF-8"> <meta name="description" content={description}> <title>{title}</title> </head> <body> <header> <p>Опубликовано: {publishDate}</p> <p>Просмотров: {viewCount}</p> </header> <main> <slot /> </main> </body></html>Макеты для Markdown
Заголовок раздела «Макеты для Markdown»Макеты особенно полезны для отдельных страниц Markdown, которые сами по себе не имеют форматирования.
Astro поддерживает специальное свойство layout в блоке метаданных (frontmatter) для отдельных .md файлов в папке src/pages/. С его помощью можно указать, какой .astro компонент использовать в качестве макета. Этот компонент обеспечит наличие тегов <head>, стилей и общей структуры страницы.
Свойство layout не является специальным при использовании коллекций контента.
---layout: ../layouts/BlogPostLayout.astrotitle: "Привет, мир!"author: "Мэтью Филлипс"date: "09 авг 2022"---Все свойства из этого блока доступны макету через Astro.props.
Свойство `layout` — единственное, которое Astro обрабатывает особым образом.Типичный макет для Markdown-страницы включает:
- Пропс
frontmatterдля доступа к метаданным страницы. - Слот по умолчанию
<slot />для рендеринга самого контента.
---// 1. Пропс frontmatter дает доступ к метаданнымconst { frontmatter } = Astro.props;---<html> <head> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta charset="utf-8"> <title>{frontmatter.title}</title> </head> <body> <!-- Общие элементы интерфейса --> <h1>{frontmatter.title} (автор: {frontmatter.author})</h1> <!-- 2. Сюда попадет скомпилированный HTML из Markdown --> <slot /> <p>Дата публикации: {frontmatter.date}</p> </body></html>Вы можете типизировать пропсы макета с помощью хелпера MarkdownLayoutProps:
---import type { MarkdownLayoutProps } from 'astro';
type Props = MarkdownLayoutProps<{ // Типизация свойств из frontmatter title: string; author: string; date: string;}>;
const { frontmatter, url } = Astro.props;---<html> <head> <meta charset="utf-8"> <link rel="canonical" href={new URL(url, Astro.site).pathname}> <title>{frontmatter.title}</title> </head> <body> <h1>{frontmatter.title} от {frontmatter.author}</h1> <slot /> <p>Дата: {frontmatter.date}</p> </body></html>Пропсы макетов Markdown
Заголовок раздела «Пропсы макетов Markdown»Макету Markdown доступны следующие данные через Astro.props:
file— абсолютный путь к файлу (например,/home/user/projects/.../file.md).url— URL страницы (например,/ru/guides/markdown-content).frontmatter— все метаданные из документа Markdown или MDX.frontmatter.file— то же, что и свойствоfileверхнего уровня.frontmatter.url— то же, что и свойствоurlверхнего уровня.
headings— список заголовков (h1->h6) в документе с их метаданными. Тип:{ depth: number; slug: string; text: string }[].rawContent()— функция, возвращающая исходный Markdown-текст в виде строки.compiledContent()— асинхронная функция, возвращающая скомпилированный HTML-код в виде строки.
Макету Markdown доступны те же свойства, что и самому файлу, но с двумя отличиями:
- Заголовки доступны через массив
headings, а не функциюgetHeadings(). fileиurlтакже доступны внутри объектаfrontmatter.
Ручной импорт макетов (MDX)
Заголовок раздела «Ручной импорт макетов (MDX)»Свойство layout также работает в файлах MDX.
Однако в MDX можно импортировать макет как обычный компонент. В этом случае он не получит пропсы автоматически — их нужно передать явно:
---layout: ../../layouts/BaseLayout.astrotitle: 'Мой первый пост на MDX'publishDate: '21 сентября 2022'---import BaseLayout from '../../layouts/BaseLayout.astro';
export function fancyJsHelper() { return "Это можно сделать только в MDX!";}
<BaseLayout title={frontmatter.title} fancyJsHelper={fancyJsHelper}> Добро пожаловать в мой новый блог на Astro с поддержкой MDX!</BaseLayout>В макете контент MDX попадет в слот <slot />:
---const { title, fancyJsHelper } = Astro.props;---<html> <head> <meta charset="utf-8"> </head> <body> <h1>{title}</h1> <slot /> <!-- контент вставится сюда --> <p>{fancyJsHelper()}</p> </body></html>При использовании любого макета (через layout или импорт) вы должны сами добавить тег <meta charset="utf-8">, так как Astro не добавляет его автоматически для MDX.
Вложенные макеты
Заголовок раздела «Вложенные макеты»Макеты могут быть вложенными. Это позволяет создавать гибкие шаблоны, переиспользуя общие части.
Например, BlogPostLayout.astro может отвечать за стиль статьи, а общий BaseLayout.astro — за навигацию, подвал и SEO.
---import BaseLayout from './BaseLayout.astro';const { frontmatter } = Astro.props;---<BaseLayout url={frontmatter.url}> <h1>{frontmatter.title}</h1> <h2>Автор: {frontmatter.author}</h2> <slot /></BaseLayout>