Chuyển đến nội dung chính

第 9 課:Nuxt 3 和基於檔案的路由

Nuxt 3 概述、自動導入、基於檔案的路由。佈局、頁面、錯誤處理。 nuxt.config.ts,執行階段配置。 Nuxt 開發工具。目錄結構。

💻 程式設計 — 第 9 課 第 9 課:Nuxt 3 和基於檔案的路由

Vue.js 和 Nuxt:從基礎到高級

第 3 部分:Nuxt 3 基礎知識

亞洲開發網

1.創建Nuxt 3項目

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

2. 目錄結構

my-nuxt-app/
├── app.vue            # Root component
├── nuxt.config.ts     # Nuxt configuration
├── pages/             # File-based routing
│   ├── index.vue      # /
│   ├── about.vue      # /about
│   └── blog/
│       ├── index.vue  # /blog
│       └── [slug].vue # /blog/:slug
├── components/        # Auto-imported components
├── composables/       # Auto-imported composables
├── layouts/           # Layout components
├── middleware/         # Route middleware
├── plugins/           # Nuxt plugins
├── server/            # Server routes (Nitro)
│   ├── api/
│   └── middleware/
├── public/            # Static files
├── assets/            # Build assets
└── utils/             # Auto-imported utilities

3. 基於檔案的路由

pages/
├── index.vue              → /
├── about.vue              → /about
├── blog/
│   ├── index.vue          → /blog
│   └── [slug].vue         → /blog/:slug
├── users/
│   ├── [id]/
│   │   ├── index.vue      → /users/:id
│   │   └── edit.vue       → /users/:id/edit
├── [[...slug]].vue        → catch-all (404)
<!-- pages/blog/[slug].vue -->
<script setup lang="ts">
const route = useRoute()
const slug = route.params.slug as string

const { data: post } = await useFetch(`/api/posts/${slug}`)
</script>

<template>
  <article v-if="post">
    <h1>{{ post.title }}</h1>
    <div v-html="post.content" />
  </article>
</template>

4. 佈局

<!-- layouts/default.vue -->
<template>
  <div class="min-h-screen">
    <AppHeader />
    <main class="container mx-auto px-4 py-8">
      <slot />
    </main>
    <AppFooter />
  </div>
</template>

<!-- layouts/dashboard.vue -->
<template>
  <div class="flex">
    <Sidebar />
    <main class="flex-1 p-6">
      <slot />
    </main>
  </div>
</template>

<!-- pages/dashboard.vue — use specific layout -->
<script setup lang="ts">
definePageMeta({
  layout: 'dashboard',
})
</script>

5. nuxt.config.ts

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

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

  runtimeConfig: {
    // Server-only (process.env)
    databaseUrl: process.env.DATABASE_URL,
    jwtSecret: process.env.JWT_SECRET,

    // Public (exposed to client)
    public: {
      apiBase: process.env.NUXT_PUBLIC_API_BASE || '/api',
      appName: 'My App',
    },
  },

  app: {
    head: {
      title: 'My Nuxt App',
      meta: [
        { name: 'description', content: 'Ứng dụng Nuxt 3' },
      ],
    },
  },

  compatibilityDate: '2025-01-01',
})

6. 自動導入

<script setup lang="ts">
// Không cần import — tất cả auto-imported!
const route = useRoute()           // vue-router
const config = useRuntimeConfig()  // nuxt
const { data } = await useFetch('/api/data') // nuxt

// Components trong /components/ cũng auto-imported
// Composables trong /composables/ cũng auto-imported
// Utils trong /utils/ cũng auto-imported
</script>

7. 錯誤處理

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

function handleClear() {
  clearError({ redirect: '/' })
}
</script>

<template>
  <div class="text-center py-20">
    <h1 class="text-6xl font-bold">{{ error.statusCode }}</h1>
    <p>{{ error.message }}</p>
    <button @click="handleClear">Về trang chủ</button>
  </div>
</template>

下一篇: 數據獲取和SSR — useFetch、useAsyncData、渲染模式。