Компоненты
Компоненты Astro являются основными строительными блоками любого проекта Astro. Они представляют собой HTML шаблоны, которые не требуют выполнения на стороне клиента. Определить компонент Astro можно по расширению файла: .astro
.
Компоненты Astro чрезвычайно гибки. Часто компонент Astro будет содержать некоторый повторно используемый UI на странице, например заголовок или карточку профиля. В других случаях компонент Astro может содержать небольшой фрагмент HTML, например набор общих <meta>
тегов, которые упрощают работу с SEO. Компоненты Astro могут даже содержать макет страницы целиком.
Самое главное, что нужно знать о компонентах Astro, - это то, что они не отрисовываются на клиенте. Они преобразуются в HTML либо во время сборки, либо с использованием рендеринга на стороне сервера (SSR) (EN). Вы можете включить JavaScript-код внутри вашего компонента frontmatter, и он весь будет удален с конечной страницы, отправленной в браузеры ваших пользователей. В результате получается более быстрый сайт с нулевым использованием JavaScript по умолчанию.
Когда вашему компоненту Astro действительно требуется интерактивность на стороне клиента, вы можете добавить стандартные теги HTML <script>
или компоненты UI фреймворков (EN).
Структура компонента
Компонент Astro состоит из двух основных частей: Скрипта компонента и Шаблона компонента. Каждая часть выполняет свою работу, но вместе они обеспечивают структуру, которая одновременно проста в использовании и достаточно выразительна, чтобы справиться с тем, что вы захотите создать.
---// Скрипт компонента (JavaScript)---<!-- Шаблон компонента (HTML + JS Expressions) -->
Скрипт компонента
Astro использует ограждение кода (---
) для идентификации скрипта в вашем компоненте Astro. Если вы когда-либо писали Markdown раньше, возможно, вы уже знакомы с похожей концепцией, называемой frontmatter. Идея Astro о скрипте компонента была непосредственно вдохновлена этой концепцией.
Вы можете использовать скрипт компонента для написания любого кода JavaScript, необходимого для визуализации шаблона. Это может включать в себя:
- импорт других Astro компонентов
- импорт компонентов из других фреймворков, таких как React
- импорт данных, например файла JSON
- получение контента из API или базы данных
- создание переменных, на которые вы будете ссылаться в своем шаблоне
---import SomeAstroComponent from '../components/SomeAstroComponent.astro';import SomeReactComponent from '../components/SomeReactComponent.jsx';import someData from '../data/pokemon.json';
// Доступ к входным параметрам компонента, таким как `<X title="Hello, World" />`const {title} = Astro.props;// Получение внешних данных, даже из приватного API или базы данныхconst data = await fetch('SOME_SECRET_API_URL/users').then(r => r.json());---<!-- Здесь ваш шаблон! -->
Ограждение кода предназначено для того, чтобы гарантировать, что JavaScript, который вы пишете в нем, не ускользнет в ваше внешнее приложение и не попадет в руки вашего пользователя. Вы можете безопасно писать здесь дорогостоящий или конфиденциальный код (например, вызов вашей приватной базы данных), не беспокоясь о том, что он когда-либо попадет в браузер вашего пользователя.
Вы даже можете использовать TypeScript в скрипте вашего компонента!
Шаблон компонента
Шаблон компонента находится под ограждением кода и определяет вывод HTML вашего компонента.
Если вы напишете здесь простой HTML, ваш компонент будет отображать этот HTML на любой странице Astro, в которую он импортирован и используется.
Однако, синтаксис Astro так же поддерживает JavaScript выражения, Astro <style>
(EN) и <script>
теги, импортированные компоненты, и специальные Astro директивы (EN). Данные и значения, определенные в скрипте компонента, можно использовать в шаблоне компонента для создания динамически создаваемого HTML.
---// Здесь ваш скрипт компонента!import Banner from '../components/Banner.astro';import ReactPokemonComponent from '../components/ReactPokemonComponent.jsx';const myFavoritePokemon = [/* ... */];const { title } = Astro.props;---<!-- Поддерживаются HTML коментарии! -->{/* JS comment syntax is also valid! */}
<Banner /><h1>Hello, world!</h1>
<!-- Используйте входные параметры и другие переменные из скрипта компонента.: --><p>{title}</p>
<!-- Включите другие компоненты инфраструктуры пользовательского интерфейса с помощью директивы `client`: для гидратации: --><ReactPokemonComponent client:visible />
<!-- Смешивайте HTML с выражениями JavaScript, аналогично JSX.: --><ul> {myFavoritePokemon.map((data) => <li>{data.name}</li>)}</ul>
<!-- Используйте директиву шаблона для создания имен классов из нескольких строк или даже объектов! --><p class:list={["add", "dynamic", {classNames: true}]} />
Компонентный дизайн
Компоненты спроектированы так, чтобы их можно было повторно использовать и компоновать. Вы можете использовать компоненты внутри других компонентов для создания более продвинутого пользовательского интерфейса. Например, компонент Button
можно использовать для создания компонента ButtonGroup
:
---import Button from './Button.astro';---<div> <Button title="Button 1" /> <Button title="Button 2" /> <Button title="Button 3" /></div>
Входные параметры компонента
Компонент Astro может определять и принимать параметры. Эти входные параметры затем становятся доступными для шаблона компонента для рендеринга HTML. Входные параметры доступны в глобальном объекте Astro.props
в вашем скрипте.
Вот пример компонента, который получает входные параметры greeting
и name
. Обратите внимание, что получаемые входные параметры деструктурированы из глобального объекта Astro.props
.
---// Применение: <GreetingHeadline greeting="Howdy" name="Partner" />const { greeting, name } = Astro.props;---<h2>{greeting}, {name}!</h2>
Этот компонент при импорте и визуализации в других компонентах Astro, макетах или страницах может передавать эти параметры в качестве атрибутов:
---import GreetingHeadline from './GreetingHeadline.astro';const name = "Astro"---<h1>Поздравительная открытка</h1><GreetingHeadline greeting="Hi" name={name} /><p>Надеюсь, у Вас будет замечательный день!</p>
Вы также можете определить свои входные параметры с помощью TypeScript с интерфейсом типа Props
. Astro автоматически подхватит интерфейс Props
в вашем frontmatter и выдаст предупреждения/ошибки типа. Этим входным параметрам также могут быть присвоены значения по умолчанию при деструктуризации из Astro.props
.
---interface Props { name: string; greeting?: string;}
const { greeting = "Hello", name } = Astro.props;---<h2>{greeting}, {name}!</h2>
Свойствам компонента могут быть присвоены значения по умолчанию, которые можно использовать, если они не указаны.
---const { greeting = "Hello", name = "Astronaut" } = Astro.props;---<h2>{greeting}, {name}!</h2>
Слоты
<slot />
это заполнитель для внешнего HTML-содержимого, позволяющий вставлять дочерние элементы из других файлов в шаблон компонента.
По умолчанию все дочерние элементы, переданные компоненту, будут отображаться в его <slot />
В отличие от входных параметров, которые являются атрибутами, передаваемыми компоненту Astro, доступными для использования во всем вашем компоненте с помощью Astro.props
, слоты отображают дочерние элементы HTML там, где они написаны.
---import Header from './Header.astro';import Logo from './Logo.astro';import Footer from './Footer.astro';
const { title } = Astro.props---<div id="content-wrapper"> <Header /> <Logo /> <h1>{title}</h1> <slot /> <!-- дочерний элемент будет здесь --> <Footer /></div>
---import Wrapper from '../components/Wrapper.astro';---<Wrapper title="Страница Фреда"> <h2>Все о Фреде</h2> <p>Вот некоторые сведения о Фреде.</p></Wrapper>
Этот шаблон является основой Astro Макетов: целая страница HTML-контента может быть «обернута» тегами <SomeLayoutComponent></SomeLayoutComponent>
и передана компоненту для отрисовки внутри определенных в нем общих элементов страницы.
Именованые слоты
Компонент Astro также может иметь именованные слоты. Это позволяет передавать в местоположение слота только элементы HTML с соответствующим именем слота.
Слоты именуются с помощью атрибута name
:
---import Header from './Header.astro';import Logo from './Logo.astro';import Footer from './Footer.astro';
const { title } = Astro.props---<div id="content-wrapper"> <Header /> <slot name="after-header"/> <!-- дочерние элементы с атрибутом `slot="after-header"` будут находится здесь --> <Logo /> <h1>{title}</h1> <slot /> <!-- дочерние элементы без `slot`, или с `slot="default"` будут находится здесь --> <Footer /> <slot name="after-footer"/> <!-- дочерние элементы с атрибутом `slot="after-footer"` будут находится здесь --></div>
Чтобы внедрить HTML-контент в определенный слот, используйте атрибут slot
в любом дочернем элементе, чтобы указать имя слота. Все остальные дочерние элементы компонента будут вставлены в стандартный (безымянный) <slot />
.
---import Wrapper from '../components/Wrapper.astro';---<Wrapper title="Fred's Page"> <img src="https://my.photo/fred.jpg" slot="after-header"> <h2>Все о Фреде</h2> <p>Вот некоторые сведения о Фреде.</p> <p slot="after-footer">Авторское право 2022</p></Wrapper>
Используйте атрибут slot="my-slot"
в дочернем элементе, который вы хотите передать в соответствующий заполнитель <slot name="my-slot" />
в вашем компоненте.
Обратите внимание, что именованные слоты должны быть непосредственными дочерними элементами компонента. Вы не можете передавать именованные слоты через вложенные элементы.
Именованные слоты также можно передавать в компоненты UI фреймворков (EN)!
Имя астро-слота не может быть сгенерировано динамически, например, в функции map. Если такая возможность необходима в компонентах UI фреймворка, то, возможно, лучше генерировать эти динамические слоты в самом фреймворке.
Резервный контент
Слоты также могут отображать резервный контент. Когда в слот не передаются соответствующие дочерние элементы, элемент <slot />
отобразит свои собственные дочерние элементы-заполнители.
---import Header from './Header.astro';import Logo from './Logo.astro';import Footer from './Footer.astro';
const { title } = Astro.props---<div id="content-wrapper"> <Header /> <Logo /> <h1>{title}</h1> <slot> <p>Это резервное содержимое, если в слот не передан дочерний элемент</p> </slot> <Footer /></div>
Передающие слоты
Слоты могут быть перенесены на другие компоненты. Например, при создании вложенных макетов:
------
<html lang="en"> <head> <meta charset="utf-8" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <meta name="viewport" content="width=device-width" /> <meta name="generator" content={Astro.generator} /> <slot name="head"/> </head> <body> <slot /> </body></html>
---import BaseLayout from "./BaseLayout.astro";---
<BaseLayout> <slot name="head" slot="head"/> <slot /></BaseLayout>
Именованные слоты могут быть переданы другому компоненту, используя атрибуты name
и slot
в теге <slot />
Теперь слоты по умолчанию и head
, переданные в HomeLayout
, будут перенесены в родительский BaseLayout
---import HomeLayout from "../layouts/HomeLayout.astro";---
<HomeLayout> <title slot="head">Astro</title> <h1>Astro</h1></HomeLayout>
HTML-компоненты
Astro поддерживает импорт и использование .html
файлов в качестве компонентов или размещение этих файлов в подкаталоге src/pages/
в качестве страниц. Возможно, вам захочется использовать HTML-компоненты, если вы повторно используете код с существующего сайта, созданного без фреймворка, или если вы хотите убедиться, что ваш компонент не имеет динамических функций.
HTML-компоненты должны содержать только валидный HTML, и поэтому в них отсутствуют ключевые функции Astro компонента:
- Они не поддерживают frontmatter, импорт на стороне сервера или динамические выражения.
- Любые теги
<script>
остаются необъединенными и обрабатываются так, как если бы у них былоis:inline
. - Они могут только ссылаться на ресурсы, которые находятся в папке
public/
.
Элемент <slot />
внутри HTML-компонента будет работать так же, как и в компоненте Astro. Для того, чтобы использовать элемент slot веб-компонента HTML добавьте is:inline
к вашему элементу <slot>
.
Следующие шаги
📚 Узнайте как использовать компоненты UI фреймворков (EN) в вашем Astro проекте.
Learn