Скрипты в компонентах
Не каждой кнопке нужен React. Для простого поведения — открыть меню, скопировать ссылку, переключить тему — хватит обычного JavaScript в теге <script> внутри компонента .astro. Astro обработает такой скрипт при сборке и подключит его к странице.
Кнопка «Скопировать ссылку»
Создайте src/components/CopyLink.astro:
<button class="copy-link">Скопировать ссылку</button>
<script>
const buttons = document.querySelectorAll('.copy-link');
buttons.forEach((button) => {
button.addEventListener('click', async () => {
await navigator.clipboard.writeText(location.href);
button.textContent = 'Скопировано';
});
});
</script>Вставьте <CopyLink /> в страницу статьи src/pages/posts/[id].astro после <Content />. Откройте статью и нажмите кнопку: адрес страницы окажется в буфере обмена, а надпись сменится на «Скопировано».
Что делает Astro со скриптом
| Особенность | Что это значит |
|---|---|
| Модуль | Скрипт работает как type="module": можно писать import |
| TypeScript | Внутри можно писать на TypeScript |
| Один раз | Если компонент стоит на странице трижды, скрипт подключится один раз |
| Сборка | Код собирается и сжимается в отдельный файл |
Из-за «одного раза» скрипт ищет все кнопки через querySelectorAll, а не одну: так он обслужит каждый экземпляр компонента.
Данные из фронтматтера
Скрипт выполняется в браузере и не видит переменных фронтматтера. Данные передают через атрибуты data-*:
---
const { title } = Astro.props;
---
<button class="share" data-title={title}>Поделиться</button>
<script>
document.querySelectorAll<HTMLButtonElement>('.share').forEach((button) => {
button.addEventListener('click', () => {
const title = button.dataset.title;
navigator.share({ title, url: location.href });
});
});
</script>Значение пропса title попадает в HTML-атрибут, а скрипт читает его из dataset. В браузерах, где есть меню «Поделиться», нажатие откроет его с названием статьи. Уточнение <HTMLButtonElement> сообщает TypeScript, что найдены кнопки, — иначе редактор не знает о поле dataset.
Скрипт без обработки
Атрибут is:inline оставляет скрипт как есть: Astro не собирает его и вставляет на каждое место, где стоит компонент. Так подключают сторонние фрагменты, например код счётчика посещений. Скрипт из папки public/, подключённый через атрибут src, тоже помечают is:inline.
Частая ошибка
Ищут элемент через document.querySelector('button') и получают не ту кнопку — первую на странице, а не кнопку своего компонента. Давайте элементам компонента уникальный класс или атрибут data-* и выбирайте по нему.