搜索

PythonReactSEOPDF
GitHub Skill

nuxt

Builds applications with Nuxt 3 including pages, layouts, composables, server routes, and data fetching. Use when creating Vue applications with SSR, building full-stack Vue apps, or needing file-based routing with Vue.

mgd34msu☆ 3 仓库 Stars0 仓库 Forks

安装与使用

请根据来源仓库和你的 AI 工具说明安装此技能。先阅读技能文件和依赖要求,再添加到工作流。

查看来源 ↗使用指南

技能说明

Nuxt 3

The intuitive Vue framework for building full-stack web applications.

Quick Start

Create project:

npx nuxi@latest init my-app
cd my-app
npm install
npm run dev

Project Structure

my-app/
  app.vue           # Root component
  nuxt.config.ts    # Configuration
  pages/            # File-based routing
  components/       # Auto-imported components
  composables/      # Auto-imported composables
  layouts/          # Page layouts
  server/           # Server routes & API
  middleware/       # Route middleware
  plugins/          # Vue plugins
  public/           # Static assets
  assets/           # Processed assets

Pages & Routing

Basic Pages
<!-- pages/index.vue -->
<template>
  <div>
    <h1>Home Page</h1>
    <NuxtLink to="/about">About</NuxtLink>
  </div>
</template>
Dynamic Routes
<!-- pages/users/[id].vue -->
<script setup lang="ts">
const route = useRoute();
const userId = route.params.id;
</script>

<template>
  <div>User ID: {{ userId }}</div>
</template>
Catch-All Routes
<!-- pages/[...slug].vue -->
<script setup lang="ts">
const route = useRoute();
// /a/b/c -> slug = ['a', 'b', 'c']
const segments = route.params.slug;
</script>
Nested Routes
pages/
  users/
    [id]/
      index.vue      # /users/:id
      profile.vue    # /users/:id/profile
      settings.vue   # /users/:id/settings

Layouts

Default Layout
<!-- layouts/default.vue -->
<template>
  <div>
    <AppHeader />
    <main>
      <slot />
    </main>
    <AppFooter />
  </div>
</template>
Custom Layout
<!-- layouts/admin.vue -->
<template>
  <div class="admin-layout">
    <AdminSidebar />
    <div class="admin-content">
      <slot />
    </div>
  </div>
</template>
<!-- pages/admin/dashboard.vue -->
<script setup lang="ts">
definePageMeta({
  layout: 'admin',
});
</script>

<template>
  <div>Admin Dashboard</div>
</template>

Data Fetching

useFetch
<script setup lang="ts">
// Automatic caching and deduplication
const { data, pending, error, refresh } = await useFetch('/api/users');

// With options
const { data: posts } = await useFetch('/api/posts', {
  query: { limit: 10 },
  pick: ['id', 'title'], // Only pick specific fields
  transform: (data) => data.map(post => post.title),
});
</script>

<template>
  <div v-if="pending">Loading...</div>
  <div v-else-if="error">Error: {{ error.message }}</div>
  <ul v-else>
    <li v-for="user in data" :key="user.id">{{ user.name }}</li>
  </ul>
</template>
useAsyncData
<script setup lang="ts">
// For custom async operations
const { data, pending } = await useAsyncData('users', () => {
  return $fetch('/api/users');
});

// With lazy loading
const { data: lazyData } = await useAsyncData(
  'lazy-users',
  () => $fetch('/api/users'),
  { lazy: true }
);
</script>
$fetch
<script setup lang="ts">
// Direct fetch (no SSR hydration)
async function createUser(userData: User) {
  const newUser = await $fetch('/api/users', {
    method: 'POST',
    body: userData,
  });
  return newUser;
}
</script>

State Management

useState
<script setup lang="ts">
// Shared reactive state across components
const counter = useState('counter', () => 0);

function increment() {
  counter.value++;
}
</script>
Composables
// composables/useCounter.ts
export function useCounter(initial = 0) {
  const count = useState('counter', () => initial);

  function increment() {
    count.value++;
  }

  function decrement() {
    count.value--;
  }

  return { count, increment, decrement };
}
<!-- Any component - auto-imported -->
<script setup lang="ts">
const { count, increment } = useCounter(10);
</script>

Server Routes

API Endpoints
// server/api/users.get.ts
export default defineEventHandler(async (event) => {
  const users = await prisma.user.findMany();
  return users;
});

// server/api/users.post.ts
export default defineEventHandler(async (event) => {
  const body = await readBody(event);
  const user = await prisma.user.create({ data: body });
  return user;
});
Dynamic Routes
// server/api/users/[id].get.ts
export default defineEventHandler(async (event) => {
  const id = getRouterParam(event, 'id');
  const user = await prisma.user.findUnique({ where: { id } });

  if (!user) {
    throw createError({
      statusCode: 404,
      message: 'User not found',
    });
  }

  return user;
});
Query Parameters
// server/api/search.get.ts
export default defineEventHandler(async (event) => {
  const query = getQuery(event);
  // /api/search?q=test&limit=10
  const { q, limit = 10 } = query;

  return await search(q, Number(limit));
});

Middleware

Route Middleware
// middleware/auth.ts
export default defineNuxtRouteMiddleware((to, from) => {
  const { loggedIn } = useUserSession();

  if (!loggedIn.value) {
    return navigateTo('/login');
  }
});
<!-- pages/dashboard.vue -->
<script setup lang="ts">
definePageMeta({
  middleware: 'auth',
});
</script>
Global Middleware
// middleware/logger.global.ts
export default defineNuxtRouteMiddleware((to, from) => {
  console.log(`Navigating from ${from.path} to ${to.path}`);
});
Server Middleware
// server/middleware/log.ts
export default defineEventHandler((event) => {
  console.log('Request:', event.path);
});

Components

Auto-imports
<!-- components/AppHeader.vue -->
<template>
  <header>
    <NuxtLink to="/">Home</NuxtLink>
  </header>
</template>

<!-- Automatically available in any page/component -->
<template>
  <div>
    <AppHeader />
  </div>
</template>
Nested Components
components/
  base/
    Button.vue    # <BaseButton />
    Input.vue     # <BaseInput />
  user/
    Avatar.vue    # <UserAvatar />

SEO & Meta

<script setup lang="ts">
useHead({
  title: 'My Page',
  meta: [
    { name: 'description', content: 'Page description' },
    { property: 'og:title', content: 'My Page' },
  ],
  link: [
    { rel: 'canonical', href: 'https://example.com/page' },
  ],
});

// Or use useSeoMeta
useSeoMeta({
  title: 'My Page',
  description: 'Page description',
  ogTitle: 'My Page',
  ogDescription: 'Page description',
  ogImage: 'https://example.com/image.png',
});
</script>

Configuration

// nuxt.config.ts
export default defineNuxtConfig({
  devtools: { enabled: true },

  modules: [
    '@nuxt/ui',
    '@pinia/nuxt',
    '@nuxtjs/tailwindcss',
  ],

  runtimeConfig: {
    // Server-only
    apiSecret: process.env.API_SECRET,
    // Public (exposed to client)
    public: {
      apiBase: process.env.API_BASE || 'http://localhost:3000',
    },
  },

  app: {
    head: {
      title: 'My App',
      meta: [
        { name: 'description', content: 'My app description' },
      ],
    },
  },

  routeRules: {
    '/': { prerender: true },
    '/api/**': { cors: true },
    '/admin/**': { ssr: false },
  },
});

Rendering Modes

// nuxt.config.ts
export default defineNuxtConfig({
  // Global SSR setting
  ssr: true,

  // Per-route rules
  routeRules: {
    '/': { prerender: true },           // Static at build
    '/blog/**': { isr: 3600 },          // ISR with 1hr revalidation
    '/admin/**': { ssr: false },        // Client-only SPA
    '/api/**': { cors: true },          // API routes
  },
});

Plugins

// plugins/my-plugin.ts
export default defineNuxtPlugin((nuxtApp) => {
  return {
    provide: {
      hello: (name: string) => `Hello ${name}!`,
    },
  };
});
<script setup lang="ts">
const { $hello } = useNuxtApp();
const greeting = $hello('World'); // "Hello World!"
</script>

Error Handling

<!-- error.vue -->
<script setup lang="ts">
const props = defineProps<{
  error: {
    statusCode: number;
    message: string;
  };
}>();

const handleError = () => clearError({ redirect: '/' });
</script>

<template>
  <div>
    <h1>{{ error.statusCode }}</h1>
    <p>{{ error.message }}</p>
    <button @click="handleError">Go Home</button>
  </div>
</template>

Best Practices

  1. Use composables - Extract reusable logic
  2. Leverage auto-imports - Components, composables, utils
  3. Use server routes - API endpoints in same project
  4. Configure rendering - SSR, SSG, ISR per route
  5. Use TypeScript - Full type safety

Common Mistakes

Mistake Fix
Calling composables outside setup Only use in setup or other composables
Using reactive in server routes Server routes are stateless
Missing await on useFetch Always await data fetching
Not handling loading states Check pending before data
Hardcoding env variables Use runtimeConfig

Reference Files

使用示例

查看来源仓库中的使用示例与配置说明。

查看来源 ↗

来源历史

收录时间
2026-01-20
索引更新时间
2026-01-28
Branch
main

收录与同步日期属于本站记录。源码修改历史请查看来源仓库。

GitHub ↗

chat Comments (0)

chat_bubble_outline

No comments yet. Be the first to share your thoughts!