Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
useAsyncData в Nuxt.js: опции и конфигурация
useAsyncData — это композабл (composable) из Nuxt 3, который предоставляет мощный механизм для загрузки и управления асинхронными данными на сервере и клиенте. Это ключевой инструмент для работы с SSR/SSG.
Основная сигнатура
const {
data, // Загруженные данные
pending, // Флаг загрузки
error, // Объект ошибки
refresh // Функция для переза грузки
} = await useAsyncData(
key, // Уникальный ключ кеша
() => fetch(...), // Async функция
options // Опции
);
Основные опции useAsyncData
1. server (boolean) — SSR контроль
// Загружать данные на сервере
const { data } = await useAsyncData(
"posts",
() => fetchPosts(),
{ server: true } // По умолчанию true
);
// Загружать только на клиенте
const { data } = await useAsyncData(
"user-preferences",
() => fetchPreferences(),
{ server: false } // Избегаем SSR
);
Когда использовать:
server: true— для публичного контента (блоги, каталоги)server: false— для приватного контента (профиль пользователя)
2. transform (function) — трансформация данных
const { data: transformedPosts } = await useAsyncData(
"posts",
() => fetchPosts(),
{
// Преобразование данных после загрузки
transform: (posts: Post[]) => {
return posts
.filter(p => p.published)
.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime())
.map(p => ({
...p,
formattedDate: new Date(p.date).toLocaleDateString("ru-RU"),
excerpt: p.content.substring(0, 100) + "..."
}));
}
}
);
3. watch (array) — отслеживание зависимостей
const route = useRoute();
const { data } = await useAsyncData(
() => `post-${route.params.id}`, // Ключ зависит от параметра
() => fetchPost(route.params.id),
{
// Перезагрузить данные при изменении зависимостей
watch: [() => route.params.id]
}
);
// Или более сложный пример
const query = ref("");
const { data } = await useAsyncData(
"search",
() => searchPosts(query.value),
{
watch: [query]
}
);
4. immediate (boolean) — автозагрузка
// По умолчанию true — загружать сразу
const { data, refresh } = await useAsyncData(
"posts",
() => fetchPosts(),
{ immediate: true } // Загрузка начнётся сразу
);
// Ленивая загрузка — данные загружаются только при вызове refresh
const { data, refresh } = await useAsyncData(
"posts",
() => fetchPosts(),
{ immediate: false } // Не загружаются автоматически
);
// Вызвать загрузку вручную
const handleLoad = () => {
refresh(); // Теперь загружаются
};
5. default (function) — значение по умолчанию
const { data } = await useAsyncData(
"posts",
() => fetchPosts(),
{
// Значение до загрузки данных
default: () => []
}
);
// Или с более сложным значением
const { data: user } = await useAsyncData(
"user",
() => fetchUser(),
{
default: () => ({
id: null,
name: "Guest",
email: null,
avatar: "/default-avatar.png"
})
}
);
6. getCachedData (function) — кастомное кеширование
const { data } = await useAsyncData(
"posts",
() => fetchPosts(),
{
// Проверка, есть ли данные в кеше
getCachedData(key, nuxtApp) {
// key — это первый параметр ("posts")
// nuxtApp — контекст приложения
// Вернуть закешированные данные если есть
return nuxtApp.static.data[key];
}
}
);
7. lazy (boolean) — ленивая загрузка
// По умолчанию false — ждём загрузки перед рендером
const { data, pending } = await useAsyncData(
"posts",
() => fetchPosts(),
{ lazy: true } // Рендерим сразу, не ждём загрузки
);
// С ленивой загрузкой
<template>
<div>
<div v-if="pending">Загрузка...</div>
<div v-else>
<PostList :posts="data" />
</div>
</div>
</template>
8. cache (number) — время кеширования (опционально)
// Некоторые версии Nuxt поддерживают TTL кеша
const { data } = await useAsyncData(
"posts",
() => fetchPosts(),
{
// Кешировать на 60 секунд
cache: 60 * 1000 // milliseconds
}
);
Практические примеры
Пример 1: Загрузка поста с трансформацией
<script setup lang="ts">
const route = useRoute();
const { data: post, pending, error, refresh } = await useAsyncData(
() => `post-${route.params.id}`,
() => $fetch(`/api/posts/${route.params.id}`),
{
server: true, // Загружать на сервере для SEO
watch: [() => route.params.id], // Перезагрузить при изменении id
transform: (raw: any) => ({
...raw,
publishedDate: new Date(raw.createdAt).toLocaleDateString("ru-RU"),
readingTime: calculateReadingTime(raw.content),
author: raw.author || { name: "Anonymous" }
})
}
);
const handleRefresh = () => {
refresh();
};
</script>
<template>
<div>
<div v-if="pending" class="loading">Загрузка поста...</div>
<div v-else-if="error" class="error">{{ error.message }}</div>
<article v-else class="post">
<h1>{{ post.title }}</h1>
<p class="meta">
<span>{{ post.publishedDate }}</span>
<span>{{ post.readingTime }} мин. чтения</span>
</p>
<div class="content" v-html="post.content" />
<button @click="handleRefresh">Обновить</button>
</article>
</div>
</template>
Пример 2: Поиск с фильтрацией
<script setup lang="ts">
const query = ref("");
const category = ref("all");
const { data: results, pending, refresh } = await useAsyncData(
() => `search-${query.value}-${category.value}`,
() => $fetch("/api/search", {
query: { q: query.value, category: category.value }
}),
{
server: false, // Поиск только на клиенте
watch: [query, category], // Перезагружать при изменении
immediate: false, // Не загружать до первого ввода
default: () => []
}
);
const handleSearch = (e: string) => {
query.value = e;
};
</script>
<template>
<div class="search">
<input
:value="query"
@input="(e) => handleSearch(e.target.value)"
placeholder="Поиск..."
/>
<select v-model="category">
<option value="all">Все категории</option>
<option value="posts">Посты</option>
<option value="users">Пользователи</option>
</select>
<div v-if="pending" class="loading">Поиск...</div>
<div v-else-if="results.length === 0" class="empty">Ничего не найдено</div>
<ul v-else class="results">
<li v-for="result in results" :key="result.id">
{{ result.title }}
</li>
</ul>
</div>
</template>
Пример 3: Приватные данные пользователя
<script setup lang="ts">
const { data: profile, refresh } = await useAsyncData(
"user-profile",
() => $fetch("/api/user/profile"),
{
server: false, // НЕ загружать на сервере (приватные данные)
watch: [], // Данные не меняются часто
default: () => null
}
);
const handleUpdateProfile = async (newData: any) => {
await $fetch("/api/user/profile", {
method: "PUT",
body: newData
});
// Обновить локальные данные
refresh();
};
</script>
<template>
<div v-if="profile" class="profile">
<h1>{{ profile.name }}</h1>
<p>{{ profile.email }}</p>
<button @click="() => handleUpdateProfile({...})">Редактировать</button>
</div>
</template>
Сравнение опций
| Опция | Тип | Значение по умолчанию | Использование |
|---|---|---|---|
| server | boolean | true | Контроль SSR |
| transform | function | undefined | Преобразование данных |
| watch | array | undefined | Отслеживание зависимостей |
| immediate | boolean | true | Автозагрузка |
| default | function | undefined | Значение до загрузки |
| getCachedData | function | undefined | Кастомное кеширование |
| lazy | boolean | false | Ленивая загрузка |
| cache | number | undefined | TTL кеша |
Best Practices
// ✅ Хороший паттерн
const { data, pending, error, refresh } = await useAsyncData(
() => `product-${route.params.id}`, // Уникальный ключ
() => $fetch(`/api/products/${route.params.id}`),
{
server: true, // Для SEO
watch: [() => route.params.id], // Реагировать на изменения маршрута
transform: (raw) => processData(raw), // Обработка данных
default: () => null // Явное значение по умолчанию
}
);
// ❌ Избегай
const { data } = await useAsyncData("same-key", fetchData); // Нет уникального ключа
Вывод: useAsyncData — мощный инструмент для управления асинхронными данными в Nuxt. Правильное использование опций позволяет создавать высокопроизводительные приложения с отличным SEO и User Experience.