Nuxt 3 路由系统详解:配置与实践指南

avatar
cmdragon 破虚
image image

扫码关注或者微信搜一搜:编程智域 前端至全栈交流与成长

第一章:Nuxt 3 简介

Nuxt 3 是什么

Nuxt 3 是一个基于 Vue 3 的服务器端渲染(SSR)框架,它为开发者提供了一个优雅的方式来构建服务端渲染的 Vue 应用程序。Nuxt 3 继承了
Nuxt 2 的核心概念和优势,同时引入了 Vue 3 的最新特性,如组合式 API(Composition API)和 TypeScript 支持,使得开发体验更加现代化和高效。

Nuxt 3 提供了一套完整的文件结构,使得项目的组织更加清晰,同时也内置了许多功能,如代码分割、静态站点生成、中间件支持等,帮助开发者快速启动和构建高质量的应用程序。

Nuxt 3 与 Nuxt 2 的区别

  1. 基于 Vue 3:Nuxt 3 完全基于 Vue 3 构建而成,这意味着它可以利用 Vue 3 的所有新特性和性能改进,如更快的状态更新、更好的类型支持等。

  2. 组合式 API:Nuxt 3 支持使用 Vue 3 的组合式 API,这使得代码更加模块化和可重用,同时也提高了开发效率。

  3. TypeScript 支持:Nuxt 3 提供了内置的 TypeScript 支持,使得类型检查和代码提示更加完善,有助于提高代码质量和减少错误。

  4. 新的配置系统:Nuxt 3 引入了一个新的配置系统,使得配置更加灵活和模块化。

  5. 改进的构建和部署流程:Nuxt 3 优化了构建和部署流程,提供了更快的构建速度和更简单的部署步骤。

  6. 实验性特性:Nuxt 3 引入了一些实验性特性,如基于文件的路由系统,使得路由定义更加直观和简单。

为什么选择 Nuxt 3

  1. 现代化的开发体验:Nuxt 3 集成了 Vue 3 的最新特性,提供了更加现代化的开发体验。

  2. 性能优化:Nuxt 3 利用 Vue 3 的性能优势,提供了更快的渲染速度和更高效的代码执行。

  3. 清晰的文件结构:Nuxt 3 的文件结构设计清晰,有助于项目管理和代码维护。

  4. 丰富的功能集:Nuxt 3 内置了许多功能,如代码分割、静态站点生成、中间件支持等,减少了开发者的重复工作。

  5. 社区支持:Nuxt 社区活跃,提供了大量的插件和主题,可以帮助开发者快速构建应用程序。

  6. 易于扩展:Nuxt 3 的模块化设计使得应用程序易于扩展,开发者可以根据需要添加新的功能。

选择 Nuxt 3,开发者可以享受到一个高效、灵活且功能丰富的框架,从而更加专注于业务逻辑的开发,而不是框架本身的配置和实现。

第二章:安装与配置

环境准备

在开始使用 Nuxt 3 之前,确保你的开发环境满足以下要求:

  1. Node.js:Nuxt 3 需要 Node.js 14.17.0 或更高版本。你可以从Node.js 官方网站下载并安装。
  2. npm 或 yarn:Node.js 包管理器,npm 是默认的,但 yarn 也可以用于管理依赖。确保已安装其中之一。
  3. Git:版本控制系统,用于管理代码仓库。
  4. 文本编辑器/IDE:推荐使用支持 Vue 3 的编辑器,如 Visual Studio Code、IntelliJ IDEA 或 WebStorm。

创建 Nuxt 3 项目

  1. 使用 CLI:在命令行中,运行以下命令来创建一个新的 Nuxt 3 项目:

    1
    2
    npx create-nuxt-app my-project

    这将创建一个名为my-project的新目录,其中包含初始的 Nuxt 3 项目结构。

  2. 选择预设:如果create-nuxt-app提示,可以选择使用预设(如@nuxtjs/kit@nuxtjs/next
    ),根据项目需求选择。默认情况下,@nuxtjs/kit适用于 SSR 项目,而@nuxtjs/next适用于 Next.js 集成。

项目结构概览

Nuxt 3 项目的基本结构如下:

  • my-project(项目根目录):

    • **pages**:包含应用程序的路由页面,每个文件夹代表一个路由层级,如pages/index.vue
    • **components**:全局复用的 Vue 组件。
    • **layouts**:定义页面布局,如基础布局、分页布局等。
    • **store**:Vuex 状态管理。
    • **scripts**:包含全局脚本,如公共模块。
    • **styles**:全局样式,可以使用 CSS、SCSS、SASS 等。
    • **.nuxt**:Nuxt 3 的内部目录,包含构建相关的文件和配置。
    • **package.json**:项目依赖和配置。
    • **nuxt.config.js**:核心配置文件,定义项目设置和构建选项。

第三章:Nuxt 3 路由基础

路由概念

在 Nuxt 3 中,路由是用于定义应用程序中不同页面之间导航的方式。Nuxt 3
基于文件系统自动生成路由配置,这意味着你不需要手动编写路由定义,只需按照约定在pages目录下创建对应的.vue文件即可。

Nuxt 3 路由配置

Nuxt 3 会根据pages目录中的文件结构自动生成路由配置。以下是一些基本的路由配置示例:

  • 对于pages/index.vue,Nuxt 会生成根路由/
  • 对于pages/about.vue,Nuxt 会生成/about路由。
  • 对于pages/user/_id.vue,Nuxt 会生成一个动态路由/user/:id

如果需要自定义路由配置,可以在nuxt.config.js文件中通过router选项进行设置。

动态路由

动态路由允许你创建基于参数的路由。在 Nuxt 3 中,动态路由通过在文件名中使用下划线_前缀来定义。以下是一个动态路由的例子:

  • 文件夹结构:pages/user/_id.vue
  • 自动生成的路由:/user/:id
  • 在组件中访问参数:this.$route.params.id

动态路由可以嵌套使用,例如pages/user/_id/post/_postId.vue会生成/user/:id/post/:postId的路由。

嵌套路由

嵌套路由(也称为二级路由)允许你在页面中嵌套其他页面或组件。在 Nuxt 3 中,你可以通过在pages目录中创建子目录来定义嵌套路由。

以下是一个嵌套路由的例子:

  • 文件夹结构:pages/user/index.vuepages/user/profile.vue

  • 自动生成的路由:

    • /user对应pages/user/index.vue
    • /user/profile对应pages/user/profile.vue

如果需要在页面中定义嵌套路由,可以在页面组件中通过<router-view>标签来指定路由出口。例如,在pages/user/index.vue
中,你可以这样定义嵌套路由:

1
2
3
4
5
<template>
<div>
<router-view></router-view> <!-- 嵌套路由出口 -->
</div>
</template>

nuxt.config.js中,你也可以使用extendRoutes方法来扩展或修改路由配置,实现更复杂的路由逻辑。

第四章:路由中间件

中间件的作用

在 Nuxt 3 中,路由中间件允许你在处理路由之前执行一些代码,这些代码可以是验证、权限检查、日志记录等。中间件可以用来确保只有满足特定条件的用户才能访问某些页面,或者在用户访问页面之前执行一些预处理操作。

编写自定义中间件

在 Nuxt 3 中,你可以通过在middleware目录下创建.js
文件来编写自定义中间件。每个文件都会被自动注册为一个中间件。中间件函数接收一个context对象,你可以通过这个对象访问路由信息、请求和响应等。

以下是一个简单的中间件示例:

1
2
3
4
5
6
7
// middleware/auth.js
export default function (context) {
if (!context.store.getters.isAuthenticated) {
context.redirect('/login')
}
}

在这个例子中,如果用户未认证,中间件会将用户重定向到登录页面。

全局中间件与局部中间件

  • 全局中间件:全局中间件会在每个路由之前执行。要定义全局中间件,只需将中间件文件放在middleware目录下,Nuxt 3
    会自动将其应用于所有路由。
  • 局部中间件:局部中间件只应用于特定的页面。你可以在pages目录下的.vue文件中通过middleware属性指定要使用的中间件。

例如,在pages/user/_id.vue中使用局部中间件:

1
2
3
4
5
<script>
export default {
middleware: 'auth', // 使用名为 'auth' 的中间件
}
</script>

在这个例子中,auth中间件只会在访问/user/:id路由时执行。

通过合理使用路由中间件,你可以增强 Nuxt 3 应用程序的安全性和用户体验,确保只有授权用户可以访问敏感页面,并在用户访问页面之前执行必要的预处理操作。

第五章:页面布局与导航

布局组件

在 Nuxt 3 中,你可以使用布局组件来定义应用程序的布局结构。布局组件是一种特殊的 Vue
组件,用于包裹应用程序的其余部分。通常,你可以在layouts目录下创建布局组件。

以下是一个简单的布局组件示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- layouts/default.vue -->
<template>
<div>
<header>
<nav>
<NuxtLink to="/">Home</NuxtLink>
<NuxtLink to="/about">About</NuxtLink>
</nav>
</header>
<main>
<slot />
</main>
<footer>
<p>right © 2023 My App</p>
</footer>
</div>
</template>

在这个例子中,我们创建了一个名为default的布局组件,它包含一个头部、主体和页脚。在页面中,你可以使用layout属性来指定要使用的布局组件。

导航链接

在 Nuxt 3 中,你可以使用<NuxtLink>组件来创建导航链接。<NuxtLink>组件是一个特殊的 Vue 组件,用于在不刷新整个页面的情况下在不同页面之间进行导航。

以下是一个简单的导航链接示例:

1
2
3
4
5
6
<template>
<div>
<NuxtLink to="/">Home</NuxtLink>
<NuxtLink to="/about">About</NuxtLink>
</div>
</template>

在这个例子中,我们创建了两个导航链接,用户可以点击这些链接在不同页面之间进行导航。

页面过渡效果

在 Nuxt 3 中,你可以使用页面过渡效果来增强用户体验。页面过渡效果可以让用户在导航不同页面时感受到流畅的过渡动画。

你可以在nuxt.config.ts文件中配置页面过渡效果,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// nuxt.config.ts
export default defineNuxtConfig({
pageTransition: {
name: 'page',
mode: 'out-in',
appear: true,
css: false,
beforeEnter(el) {
el.style.opacity = 0
},
enter(el, done) {
const animation = el.animate(
[
{ opacity: 0 },
{ opacity: 1 },
],
{
duration: 500,
easing: 'ease-in-out',
}
)

animation.onfinish = () => {
done()
}
},
leave(el, done) {
const animation = el.animate(
[
{ opacity: 1 },
{ opacity: 0 },
],
{
duration: 500,
easing: 'ease-in-out',
}
)

animation.onfinish = () => {
done()
}
},
},
})

在这个例子中,我们配置了一个名为page的页面过渡效果,它使用了一个简单的淡入淡出动画。你可以根据需要自定义页面过渡效果。

第六章:高级路由技巧

在Vue和Nuxt中,路由不仅仅是导航那么简单,它们还允许我们执行更复杂的操作,比如在页面渲染前获取数据、处理错误页面以及保护路由等。

异步数据获取

在Vue中,可以使用组件的生命周期钩子如createdmounted来获取数据。但在Nuxt中,推荐使用asyncData
方法来在服务器端渲染(SSR)之前获取数据,这样可以在页面加载前就获取到数据,提高首屏加载速度。

以下是一个使用asyncData的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
<div>
<h1>文章详情</h1>
<p>{{ article.title }}</p>
<p>{{ article.content }}</p>
</div>
</template>

<script>
export default {
async asyncData({ params, $http }) {
const response = await $http.get(`/api/articles/${params.id}`);
return {
article: response.data
};
}
}
</script>

在这个例子中,asyncData方法在服务器端被调用,通过HTTP请求获取与路由参数id对应的文章数据。

错误页面处理

在Nuxt中,可以创建专门的错误页面来处理客户端和服务器端错误。例如,可以创建一个error.vue页面来显示错误信息。

以下是一个简单的错误页面示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
<div>
<h1>发生错误</h1>
<p>抱歉,页面无法加载。</p>
<p>错误代码:{{ error.statusCode }}</p>
</div>
</template>

<script>
export default {
props: ['error'],
}
</script>

当Nuxt遇到错误时,如404或500错误,它会自动渲染这个error.vue页面,并将错误对象作为属性传递给组件。

路由守卫

路由守卫是Vue Router提供的一个功能,允许我们在导航发生前后执行代码。在Nuxt中,可以使用全局守卫、路由独享守卫和组件内守卫。

  • 全局前置守卫:使用router.beforeEach注册,例如用于检查用户权限。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
export default {
setup() {
const router = useRouter();

router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
// 检查用户是否已认证
if (!isUserAuthenticated()) {
next('/login');
} else {
next();
}
} else {
next();
}
});
}
}

  • 路由独享守卫:在路由配置中使用beforeEnter
1
2
3
4
5
6
7
8
9
10
11
12
export default {
routes: [
{
path: '/profile',
component: ProfilePage,
beforeEnter: (to, from, next) => {
// 独享守卫逻辑
}
}
]
}

  • 组件内守卫:在组件内部定义,如beforeRouteEnterbeforeRouteUpdatebeforeRouteLeave
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<template>
<div>...</div>
</template>

<script>
export default {
beforeRouteEnter(to, from, next) {
// 进入组件之前
},
beforeRouteUpdate(to, from, next) {
// 路由参数变化时
},
beforeRouteLeave(to, from, next) {
// 离开组件之前
}
}
</script>

使用路由守卫,你可以执行如权限验证、页面访问控制等操作。

第七章:实战案例分析

博客系统路由设计

在设计博客系统的路由时,需要考虑博客文章的展示、分类、标签、搜索、分页等功能。以下是一个简单的博客系统路由设计示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
export default {
routes: [
// 首页
{
path: '/',
name: 'home',
component: () => import('@/components/Home.vue')
},
// 文章列表
{
path: '/articles',
name: 'articles',
component: () => import('@/components/Articles.vue')
},
// 文章详情
{
path: '/articles/:id',
name: 'article-detail',
component: () => import('@/components/ArticleDetail.vue')
},
// 文章分类
{
path: '/categories/:category',
name: 'category',
component: () => import('@/components/Category.vue')
},
// 标签页
{
path: '/tags/:tag',
name: 'tag',
component: () => import('@/components/Tag.vue')
},
// 搜索结果
{
path: '/search',
name: 'search',
component: () => import('@/components/Search.vue')
},
// 404页面
{
path: '*',
name: '404',
component: () => import('@/components/NotFound.vue')
}
]
}

在这个设计中,:id:category:tag是动态路由参数,用于获取具体的文章、分类或标签。

电商网站路由设计

电商网站的路由设计需要考虑商品展示、分类、购物车、订单、用户账户等功能。以下是一个电商网站的路由设计示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
export default {
routes: [
// 首页
{
path: '/',
name: 'home',
component: () => import('@/components/Home.vue')
},
// 商品分类
{
path: '/category/:id',
name: 'category',
component: () => import('@/components/Category.vue')
},
// 商品详情
{
path: '/product/:id',
name: 'product-detail',
component: () => import('@/components/ProductDetail.vue')
},
// 购物车
{
path: '/cart',
name: 'cart',
component: () => import('@/components/Cart.vue')
},
// 订单确认
{
path: '/order/confirm',
name: 'order-confirm',
component: () => import('@/components/OrderConfirm.vue')
},
// 订单列表
{
path: '/orders',
name: 'orders',
component: () => import('@/components/Orders.vue')
},
// 用户账户
{
path: '/account',
name: 'account',
component: () => import('@/components/Account.vue')
},
// 登录/注册
{
path: '/login',
name: 'login',
component: () => import('@/components/Login.vue')
},
// 404页面
{
path: '*',
name: '404',
component: () => import('@/components/NotFound.vue')
}
]
}

在这个设计中,:id用于获取具体的商品或分类信息。

多语言支持的路由实现

多语言支持是跨境电商网站的重要特性。以下是一个多语言支持的路由实现示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
export default {
routes: [
{
path: '/:lang',
component: () => import('@/components/Layout.vue'),
children: [
// 首页
{
path: '/',
name: 'home',
component: () => import('@/components/Home.vue')
},
// 其他路由...
]
},
{
path: '*',
name: '404',
component: () => import('@/components/NotFound.vue')
}
]
}

在这个设计中,:lang是一个路由参数,用于表示当前页面的语言。例如,/en将显示英文版的首页,/fr
将显示法文版的首页。通过这种方式,可以为每种语言设置不同的路由和视图。

第八章:性能优化与安全

在构建大型应用时,性能和安全是至关重要的因素。在本章中,我们将讨论三个与路由相关的性能优化和安全问题:路由懒加载、路由安全性和性能监控与调试。

路由懒加载

路由懒加载是一种在需要时加载路由组件的技术,可以提高应用的初始加载速度和性能。在路由配置中,可以使用动态导入语法(import()
)来实现路由懒加载:

1
2
3
4
5
6
7
8
9
10
11
const router = new VueRouter({
routes: [
{
path: '/',
name: 'home',
component: () => import('@/components/Home.vue')
},
// 其他路由...
]
})

在这个示例中,Home组件将在访问/路径时动态导入和渲染。这意味着在应用启动时,Home组件的代码不会被加载,直到用户访问/
路径时才会加载。

路由懒加载还可以结合代码分割和按需加载来进一步优化应用性能。

路由安全性

在路由配置中,可以使用beforeEnter守卫来实现路由安全性。beforeEnter守卫是一个函数,在路由导航被确认之前被调用,可以用于检查用户是否具有访问路由所需的权限。

以下是一个简单的路由安全性示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const router = new VueRouter({
routes: [
{
path: '/admin',
name: 'admin',
component: () => import('@/components/Admin.vue'),
beforeEnter: (to, from, next) => {
// 检查用户是否登录
if (isUserLoggedIn()) {
next()
} else {
next('/login')
}
}
},
// 其他路由...
]
})

在这个示例中,beforeEnter守卫检查用户是否登录,如果用户未登录,则会重定向到登录页面。

性能监控与调试

在开发过程中,可以使用浏览器的开发工具和性能分析工具来监控和调试应用的性能。

在Chrome开发工具中,可以使用“性能”面板来记录和分析应用的性能数据,包括页面加载时间、CPU使用率、内存使用率和布局抖动等指标。

在Vue应用中,可以使用performance.mark()performance.measure()API来记录和分析应用的性能数据。以下是一个简单的性能监控示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const router = new VueRouter({
routes: [
{
path: '/',
name: 'home',
component: () => import('@/components/Home.vue'),
beforeRouteEnter: (to, from, next) => {
performance.mark('beforeRouteEnter')
next(() => {
performance.measure('beforeRouteEnter', 'beforeRouteEnter')
})
}
},
// 其他路由...
]
})

在这个示例中,beforeRouteEnter生命周期钩子记录了一个名为beforeRouteEnter
的标记,并在路由导航被确认后记录了一个名为beforeRouteEnter的度量。这些数据可以在Chrome开发工具中的“性能”面板中查看和分析。

余下文章内容请点击跳转至 个人博客页面 或者 扫码关注或者微信搜一搜:编程智域 前端至全栈交流与成长,阅读完整的文章:

往期文章推荐: