Пропустить до содержимого

Компоненты

Компоненты 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 состоит из двух основных частей: Скрипта компонента и Шаблона компонента. Каждая часть выполняет свою работу, но вместе они обеспечивают структуру, которая одновременно проста в использовании и достаточно выразительна, чтобы справиться с тем, что вы захотите создать.

src/components/EmptyComponent.astro
---
// Скрипт компонента (JavaScript)
---
<!-- Шаблон компонента (HTML + JS Expressions) -->

Скрипт компонента

Astro использует ограждение кода (---) для идентификации скрипта в вашем компоненте Astro. Если вы когда-либо писали Markdown раньше, возможно, вы уже знакомы с похожей концепцией, называемой frontmatter. Идея Astro о скрипте компонента была непосредственно вдохновлена этой концепцией.

Вы можете использовать скрипт компонента для написания любого кода JavaScript, необходимого для визуализации шаблона. Это может включать в себя:

  • импорт других Astro компонентов
  • импорт компонентов из других фреймворков, таких как React
  • импорт данных, например файла JSON
  • получение контента из API или базы данных
  • создание переменных, на которые вы будете ссылаться в своем шаблоне
src/components/MyComponent.astro
---
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, который вы пишете в нем, не ускользнет в ваше внешнее приложение и не попадет в руки вашего пользователя. Вы можете безопасно писать здесь дорогостоящий или конфиденциальный код (например, вызов вашей приватной базы данных), не беспокоясь о том, что он когда-либо попадет в браузер вашего пользователя.

Шаблон компонента

Шаблон компонента находится под ограждением кода и определяет вывод HTML вашего компонента.

Если вы напишете здесь простой HTML, ваш компонент будет отображать этот HTML на любой странице Astro, в которую он импортирован и используется.

Однако, синтаксис Astro так же поддерживает JavaScript выражения, Astro <style> (EN) и <script> теги, импортированные компоненты, и специальные Astro директивы (EN). Данные и значения, определенные в скрипте компонента, можно использовать в шаблоне компонента для создания динамически создаваемого HTML.

src/components/MyFavoritePokemon.astro
---
// Здесь ваш скрипт компонента!
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:

src/components/ButtonGroup.astro
---
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.

src/components/GreetingHeadline.astro
---
// Применение: <GreetingHeadline greeting="Howdy" name="Partner" />
const { greeting, name } = Astro.props;
---
<h2>{greeting}, {name}!</h2>

Этот компонент при импорте и визуализации в других компонентах Astro, макетах или страницах может передавать эти параметры в качестве атрибутов:

src/components/GreetingCard.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.

src/components/GreetingHeadline.astro
---
interface Props {
name: string;
greeting?: string;
}
const { greeting = "Hello", name } = Astro.props;
---
<h2>{greeting}, {name}!</h2>

Свойствам компонента могут быть присвоены значения по умолчанию, которые можно использовать, если они не указаны.

src/components/GreetingHeadline.astro
---
const { greeting = "Hello", name = "Astronaut" } = Astro.props;
---
<h2>{greeting}, {name}!</h2>

Слоты

<slot /> это заполнитель для внешнего HTML-содержимого, позволяющий вставлять дочерние элементы из других файлов в шаблон компонента.

По умолчанию все дочерние элементы, переданные компоненту, будут отображаться в его <slot />

src/components/Wrapper.astro
---
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>
src/pages/fred.astro
---
import Wrapper from '../components/Wrapper.astro';
---
<Wrapper title="Страница Фреда">
<h2>Все о Фреде</h2>
<p>Вот некоторые сведения о Фреде.</p>
</Wrapper>

Этот шаблон является основой Astro Макетов: целая страница HTML-контента может быть «обернута» тегами <SomeLayoutComponent></SomeLayoutComponent> и передана компоненту для отрисовки внутри определенных в нем общих элементов страницы.

Именованые слоты

Компонент Astro также может иметь именованные слоты. Это позволяет передавать в местоположение слота только элементы HTML с соответствующим именем слота.

Слоты именуются с помощью атрибута name:

src/components/Wrapper.astro
---
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 />.

src/pages/fred.astro
---
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" /> в вашем компоненте.

Обратите внимание, что именованные слоты должны быть непосредственными дочерними элементами компонента. Вы не можете передавать именованные слоты через вложенные элементы.

Резервный контент

Слоты также могут отображать резервный контент. Когда в слот не передаются соответствующие дочерние элементы, элемент <slot /> отобразит свои собственные дочерние элементы-заполнители.

src/components/Wrapper.astro
---
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>

Передающие слоты

Слоты могут быть перенесены на другие компоненты. Например, при создании вложенных макетов:

src/layouts/BaseLayout.astro
---
---
<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>
src/layouts/HomeLayout.astro
---
import BaseLayout from "./BaseLayout.astro";
---
<BaseLayout>
<slot name="head" slot="head"/>
<slot />
</BaseLayout>

Теперь слоты по умолчанию и head, переданные в HomeLayout, будут перенесены в родительский BaseLayout

src/pages/index.astro
---
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 компонента:

Следующие шаги

📚 Узнайте как использовать компоненты UI фреймворков (EN) в вашем Astro проекте.