Nuxt4 文件系统路由
Nuxt 的路由系统基于文件系统路由约定,你只需要在 app/pages/ 目录下创建 Vue 文件,路由就自动生成,不需要任何路由配置文件。
静态路由
app/pages/ 目录下的 .vue 文件会自动映射为对应的路由路径:
app/pages/
├── index.vue → /
├── about.vue → /about
└── contact.vue → /contact
创建 app/pages/about.vue:
<template>
<div>
<h1>关于我们</h1>
<p>这是关于页面,路由地址是 /about</p>
</div>
</template>
启动开发服务器后访问 http://localhost:3000/about 就能看到这个页面。
index.vue 是特殊文件名,代表目录的默认页面,app/pages/blog/index.vue 对应 /blog,同时子目录也可以继续嵌套,如 app/pages/blog/post.vue 对应 /blog/post。
动态路由
实际项目中经常有 /user/1、/user/2 这类路径,后面那串数字是动态的,Nuxt 用方括号 [] 表示动态参数:
app/pages/
└── user/
└── [id].vue → /user/:id(匹配 /user/1、/user/abc 等)
创建 app/pages/user/[id].vue:
<script setup>
// useRoute() 获取当前路由信息
const route = useRoute()
// route.params 包含所有动态参数
const userId = route.params.id
</script>
<template>
<div>
<h1>用户详情页</h1>
<p>当前用户 ID:{{ userId }}</p>
</div>
</template>
访问 /user/123 显示「当前用户 ID:123」,访问 /user/john 则显示「当前用户 ID:john」。
多级动态参数
app/pages/
└── post/
├── [category]/[slug].vue → /post/:category/:slug
└── [id]/edit.vue → /post/:id/edit(嵌套动态路由)
app/pages/post/[category]/[slug].vue:
<script setup>
const route = useRoute()
const { category, slug } = route.params
</script>
<template>
<div>
<p>分类:{{ category }}</p>
<p>文章别名:{{ slug }}</p>
</div>
</template>
访问 /post/tech/nuxt4-guide,会显示「分类:tech」和「文章别名:nuxt4-guide」。
通配符路由
用三点加方括号 [...slug].vue 匹配任意数量的路径段,适合做 404 兜底或路径透传:
app/pages/
└── [...slug].vue → 匹配任意深度的路径
app/pages/[...slug].vue:
<script setup>
const route = useRoute()
// slug 可能是字符串或数组
const slug = route.params.slug
</script>
<template>
<p>当前路径:{{ Array.isArray(slug) ? slug.join('/') : slug }}</p>
</template>
[...slug].vue 不匹配根路径 /。如果希望可选,即匹配 / 也匹配任意深度,用双括号 [[...slug]].vue。
嵌套路由
嵌套路由用于构建有父子层级关系的页面,比如后台管理界面,侧边栏固定,主区域根据子路由切换。
Nuxt 通过与文件夹同名的 Vue 文件实现嵌套:
app/pages/
├── admin.vue ← 父级布局(包含侧边栏和 <NuxtPage />)
└── admin/
├── index.vue → /admin
├── users.vue → /admin/users
└── settings.vue → /admin/settings
app/pages/admin.vue:
<template>
<div class="admin-layout">
<aside class="sidebar">
<ul>
<li><NuxtLink to="/admin">概览</NuxtLink></li>
<li><NuxtLink to="/admin/users">用户管理</NuxtLink></li>
</ul>
</aside>
<main class="content">
<!-- 子页面内容渲染到这里 -->
<NuxtPage />
</main>
</div>
</template>
访问 /admin/users 时,admin.vue 作为外层框架,admin/users.vue 的内容渲染在 <NuxtPage /> 的位置。
路由跳转
页面之间跳转使用 <NuxtLink> 组件:
<template>
<div>
<NuxtLink to="/">首页</NuxtLink>
<NuxtLink to="/about">关于</NuxtLink>
<NuxtLink to="/user/123">用户 123</NuxtLink>
</div>
</template>
<NuxtLink> 在客户端会自动使用前端路由跳转,不刷新页面,体验更流畅,需要用 JavaScript 编程式跳转时:
<script setup>
const router = useRouter()
function goToUser(id) {
router.push(`/user/${id}`)
}
</script>
<template>
<button @click="goToUser(456)">查看用户 456</button>
</template>
获取查询字符串
动态参数之外的 URL 查询参数(?key=value)用 route.query 获取:
访问:/search?keyword=nuxt&page=2
<script setup>
const route = useRoute()
const keyword = route.query.keyword // 'nuxt'
const page = route.query.page // '2'(字符串)
</script>
route.query 取到的值都是字符串,数字类型需要自行转换,如 Number(page)。
NuxtLink 进阶与页面元信息
高亮当前导航
<NuxtLink> 会给「当前路由」对应的链接自动加上 router-link-active 和 router-link-exact-active 两个 class,配合 CSS 就能高亮当前页的导航项:
<template>
<nav>
<NuxtLink to="/" active-class="on" class="nav-link">首页</NuxtLink>
<NuxtLink to="/about" active-class="on" class="nav-link">关于</NuxtLink>
</nav>
</template>
<style>
.nav-link.on { color: #2563eb; font-weight: 700; }
</style>
exact-active-class 只在「完整路径完全一致」时才高亮,适合首页这种不希望子页也高亮的场景。
外部链接与预取
- 链接指向其他域名时,
<NuxtLink>会自动加target="_blank"和rel="noopener";纯外部链接也可以用原生<a>。 - 默认鼠标悬停就会预取目标页代码,加快切换;不需要时加
:prefetch="false"。
用 definePageMeta 设置页面标题
除了在 app.vue 里用 useSeoMeta 设全局默认,单页也可以在 <script setup> 里用 definePageMeta 直接写页面标题:
<script setup>
definePageMeta({
title: '关于我们' // 等价于在本页调用 useHead({ title: '关于我们' })
})
</script>
definePageMeta 还能设 pageKey(强制组件重新创建)和 middleware(见中间件)、layout(见布局),把页面级元信息集中在一处声明。
路由速查表
| 场景 | 文件命名方式 | 匹配示例 |
|---|---|---|
| 静态页面 | about.vue |
/about |
| 默认页面 | index.vue |
/ 或 /blog |
| 动态参数 | [id].vue |
/user/1、/user/abc |
| 多级动态参数 | [category]/[slug].vue |
/post/tech/nuxt4 |
| 嵌套动态路由 | [id]/edit.vue |
/post/1/edit |
| 必填全匹配 | [...slug].vue |
任意路径(不含 /) |
| 可选全匹配 | [[...slug]].vue |
/ 或任意路径 |
| 嵌套路由 | admin.vue + admin/ 文件夹 |
/admin 和 /admin/users 共用框架 |
一句话总结:文件放对位置,路由自动生效,用 [] 捕捉动态参数,用 <NuxtPage /> 承载嵌套内容,用 <NuxtLink> 跳转,用 useRoute() 拿路由信息。