9. Vue в Astro
Astro поддерживает Vue 3 из коробки через официальную интеграцию. Вы можете использовать Vue Single File Components (.vue) прямо в проекте, смешивая их с Astro и другими фреймворками на одной странице.
Установка интеграции
Заголовок раздела «Установка интеграции»npx astro add vueКоманда автоматически:
- Устанавливает
@astrojs/vueиvue - Обновляет
astro.config.mjs - Настраивает компилятор Vue SFC
Конфигурация astro.config.mjs
Заголовок раздела «Конфигурация astro.config.mjs»import { defineConfig } from 'astro/config';import vue from '@astrojs/vue';
export default defineConfig({ integrations: [vue()],});Vue SFC в Astro
Заголовок раздела «Vue SFC в Astro»Vue SFCs работают точно так же, как в обычном Vue-проекте:
<script setup>import { ref } from 'vue';
const props = defineProps({ initialCount: { type: Number, default: 0 }});
const count = ref(props.initialCount);const increment = () => count.value++;const decrement = () => count.value--;</script>
<template> <div class="counter"> <button @click="decrement">−</button> <span>{{ count }}</span> <button @click="increment">+</button> </div></template>
<style scoped>.counter { display: flex; align-items: center; gap: 12px;}</style>Использование Vue компонента в .astro файле
Заголовок раздела «Использование Vue компонента в .astro файле»---import VueCounter from '../components/VueCounter.vue';import VueProductCard from '../components/VueProductCard.vue';---
<html> <body> <h1>Магазин</h1>
<!-- Vue Islands — с директивами гидратации --> <VueCounter initialCount={5} client:load /> <VueProductCard product={product} client:visible /> </body></html>Vue script setup в контексте Astro
Заголовок раздела «Vue script setup в контексте Astro»<script setup>import { ref, computed, watch } from 'vue';
const props = defineProps({ placeholder: String, items: Array,});
const query = ref('');const results = computed(() => (props.items || []).filter(item => item.toLowerCase().includes(query.value.toLowerCase()) ));
watch(query, (val) => { if (val.length > 2) { // Отправить аналитику console.log('Поиск:', val); }});</script>
<template> <div> <input v-model="query" :placeholder="placeholder" /> <ul> <li v-for="item in results" :key="item">{{ item }}</li> </ul> </div></template>Передача props из Astro в Vue
Заголовок раздела «Передача props из Astro в Vue»---import VueProductList from '../components/VueProductList.vue';
const products = await fetch('https://api.example.com/products').then(r => r.json());---
<!-- Props сериализуются и передаются в Vue как обычные props --><VueProductList client:visible :products={products} title="Популярные товары" maxItems={6}/>Vue Reactive State в Islands
Заголовок раздела «Vue Reactive State в Islands»<script setup>import { ref, computed } from 'vue';
const items = ref([]);const total = computed(() => items.value.reduce((sum, item) => sum + item.price * item.qty, 0));
const addItem = (product) => { const existing = items.value.find(i => i.id === product.id); if (existing) { existing.qty++; } else { items.value.push({ ...product, qty: 1 }); }};</script>
<template> <div class="cart"> <h3>Корзина ({{ items.length }})</h3> <div v-for="item in items" :key="item.id"> {{ item.name }} × {{ item.qty }} </div> <strong>Итого: {{ total }}₽</strong> </div></template>React + Vue + Astro на одной странице
Заголовок раздела «React + Vue + Astro на одной странице»Astro позволяет использовать несколько фреймворков одновременно. Каждый Island изолирован и управляет своим состоянием независимо:
---import ReactSearchBar from '../components/ReactSearchBar.jsx';import VueProductCard from '../components/VueProductCard.vue';import SvelteRatingWidget from '../components/SvelteRating.svelte';---
<!-- Все три фреймворка на одной странице! --><ReactSearchBar client:load /><VueProductCard client:visible product={product} /><SvelteRatingWidget client:idle productId={product.id} />