拥抱全栈框架 Nuxt | 进阶篇
前言
PS:
Nuxt 进阶知识
引入组件库
我们可以从 Nuxt Modules 中寻找想要引入的组件库,我们以 Nuxt UI 为例,介绍如何在 Nuxt 中使用组件库,进入 Nuxt UI 官网,参照文档要求进行安装。

首先,在项目根目录中打开命令行终端并输入:npx nuxi@latest module add ui
。
这样,nuxi 脚手架会自动帮我们下载 @nuxt/ui
这个第三方包并自动注册到 nuxt.config.ts
中的 modules
数组中,这样我们就可以在页面中直接使用。

示例代码:
<template>
<UButton>Button</UButton>
<UInput color="primary" variant="outline" placeholder="Search..." />
</template>
引入组件就能使用,能达到立竿见影的效果。

嵌套路由
Nuxt 和 Vue 一样,也是支持嵌套路由的,只不过在 Nuxt 中, 嵌套路由也是根据目录结构和文件的名称自动生成的,编写嵌套路由的步骤如下。
首先,创建一个一级路由,如:parent.vue
然后,创建一个与一级路由同名同级的文件夹,如:parent

其次,在 parent 文件夹下,创建一个嵌套的二级路由
其中包括:parent/child1.vue
和 parent/child1.vue
为两个二级路由页面,parent/index.vue
则为二级路由默认的页面

最后,需要在 parent.vue 中添加 NuxtPage 路由占位,以下为 parent.vue 文件中的示例代码。
<template>
<div>
<div>Parent 一级路由页面 - 公共页面</div>
<div>
<NuxtLink to="/parent">
<UButton variant="solid">导航至 parent 二级路由页面</UButton>
</NuxtLink>
<NuxtLink to="/parent/child1">
<UButton color="yellow" variant="solid">导航至 parent 二级路由页面的子页面 child1</UButton>
</NuxtLink>
<NuxtLink to="/parent/child2">
<UButton color="blue" variant="solid">导航至 parent 二级路由页面的子页面 child1</UButton>
</NuxtLink>
</div>
<!-- 嵌套二级路由 -->
<NuxtPage></NuxtPage>
</div>
</template>
<script lang="ts" setup></script>
<style scoped></style>
示例演示:

路由中间件(middleware)
Nuxt 提供了一个可定制的路由中间件,用来监听路由的导航,包括:局部和全局监听,而全局监听支持在服务器和客户端执行,路由中间件分为三种:匿名(或内联)路由中间件,命名路由中间件和全局路由中间件。
匿名(或内联)路由中间件
在页面中使用 definePageMeta
函数定义,可监听局部路由,当注册多个中间件时,会按照注册顺序来执行。
<template>
<div>我是 Parent 二级路由页面的子页面 child1</div>
</template>
<script setup>
definePageMeta({
// 路由中间件( 监听路由 )
middleware: [
// 第一个中间件
function (to, from) {
console.log(from)
console.log(to)
console.log('child1 第一个中间件')
},
// 第二个中间件
function (to, from) {
// console.log(from)
// console.log(to)
console.log('child1 第二个中间件')
},
// 第三个中间件
function (to, from) {
console.log('child1 第三个中间件')
}
]
})
</script>
<style scoped></style>
示例演示:

命名路由中间件
命名路由中间件,需要在 middleware 目录中定义,会自动加载中间件,应遵循 kebab-case 命名规范。
例如,在 /pages/middleware
文件夹下定义一个 home.ts
的中间件。

export default defineNuxtRouteMiddleware((to, from) => {
console.log(from)
console.log(to)
console.log('home 中间件')
})
然后,在需要使用的页面引入,直接以字符串的形式传入 middleware
数组中。
<template>
<div>我是 Parent 二级路由页面的子页面 child2</div>
</template>
<script setup>
definePageMeta({
// 路由中间件( 监听路由 )
middleware: ['home']
})
</script>
<style scoped></style>
示例演示:

全局路由中间件
需要定义在 middleware 目录中, 并且创建的文件要带 .global
后缀,每次路由更改都会自动运行

// 这个优先级别是比较高的
export default defineNuxtRouteMiddleware((to, from) => {
console.log('auth.global.ts 全局路由中间件')
})
然后,每次路由更改的时候都会在每个页面中执行,值得注意的是,全局路由中间件的优先级是比较高的,执行的顺序要优于其它类型的中间件。
示例演示:

路由验证( validate )
Nuxt 支持对每个页面路由进行验证,我们可以通过 definePageMeta
中的 validate
属性来对路由进行一定的规则验证。其中 validate
属性接受一个回调函数,回调函数中以 route
作为参数。
回调函数的返回值:一方面支持返回布尔类型的值来确定是否放行路由,返回 true
则放行路由,返回 false
则默认重定向到内置的 404 页面中;另一方面支持返回一个对象,例如,返回 { statusCode:401 }
,同样表示路由验证失败,返回到默认的 404 页面中。
值得一提的是,对于路由验证失败来说,也是可以自定义错误页面的,在项目根目录新建 error.vue
页面,注意不是 pages 目录中,而是项目根目录中。
<script lang="ts" setup>
// 获取动态路由的参数
const route = useRoute()
const { id } = route.params
definePageMeta({
// 路由参数的验证
validate: (route) => {
console.log(route.params.id)
// 在这里可以进行路由参数的验证,如使用正则进行验证
// 1. 返回布尔值
// return /^\d+$/.test(route.params.id as string)
// 2. 返回一个对象
return {
statusCode: 401, // 路由验证失败
statusMessage: "validata router error"
}
}
})
</script>
Nuxt 插件
Nuxt 有一个插件系统,可以在创建 Vue 应用程序时使用 Vue 插件等,Nuxt 会自动读取 plugins/ 目录中的文件,并在创建 Vue 应用程序时加载它们。
因此 Nuxt 支持自定义插件并进行扩展,创建插件有两种方式:
方式一,直接使用 useNuxtApp()
中的 provide(name, vlaue)
方法直接创建,例如:可在 app.vue 中创建。
<script setup>
// 方式一:创建插件
const nuxtApp = useNuxtApp()
nuxtApp.provide("provId", () => {
return "省份名称"
})
nuxtApp.provide("feskill", "Nuxt")
// 使用插件
console.log(nuxtApp.$provId())
console.log(nuxtApp.$feskill)
</script>
方式二,在 plugins 目录中创建插件,例如,在 plugins 目录下创建 date.ts
插件。
export default defineNuxtPlugin((nuxtApp) => {
return {
provide: {
// 自定义的插件,在创建 Vue 实例时就会自动注册
formDate: (date: string) => {
return '日期:' + date
}
}
}
})
然后在组件中使用 useNuxtApp()
方法来获取到插件中的方法
<script setup>
// 方式二:在 plugins 目录中创建插件后,可以在这里获取
const nuxtApp = useNuxtApp()
// 使用插件
console.log(nuxtApp.$formDate('2024-4-30'))
</script>
Nuxt 状态管理
Nuxt 内置 useState()
useState
是一个 SSR 友好的 ref
替换。
useState
的值将在服务端渲染后(在客户端水合期间)保留,并使用唯一键在所有组件之间共享。
useState
相比于 ref
一个最大的不同点在于 useState
是具有缓存性的,在不同的组件中多次调用同一个 useState
结果是一样的,主要用于全局状态的管理。
<script setup lang="ts">
const counter = useState('counter', () => Math.round(Math.random() * 1000))
</script>
<template>
<div>
Counter: {{ counter }}
<button @click="counter++">
+
</button>
<button @click="counter--">
-
</button>
</div>
</template>
引入 Pinia
首先,在命令行终端输入 npm i pinia @pinia/nuxt
。
然后,在 nuxt.config.ts
文件中配置 pinia
,同时设置自动导入功能。
export default defineNuxtConfig({
modules: [
// 引入 Pinia
[
"@pinia/nuxt",
{
autoImports: [
// 自动引入 `defineStore(), storeToRefs()`
"defineStore",
"storeToRefs"
]
}
]
]
})
接着,就可以在项目根目录创建 store/user.ts
文件定义全局的状态。
export const useUser = defineStore("user", {
state: () => ({
ifLogin: false
})
})
最后,在页面中获取用户的登录状态。
// 获取用户的登录状态
const store = useUser()
// storeToRefs 可直接使用,因为在 `nuxt.config.ts` 文件中已经设置自动导入 storeToRefs
const { isLogin } = storeToRefs(store)
总结
最后,建议大家学习 Nuxt 知识还是以官网为准,因为这是最权威的,时刻与官网保持同步。
在掌握最基本的 Nuxt 开发技巧之后,一定要以一个实战项目为出发点,只有这样才能融会贯通,边实战,边查资料,形成一个闭环,从开发,到测试,再到上线,途中一定会遇到很多问题,这便是成长的过程。
转载自:https://juejin.cn/post/7363287221878997028