在 nuxt3
中,希望做路由验证,可以借助 definePageMeta
实现
场景
现在有2个页面,A 页面和B页面, 从A页面跳转到B页面携带了参数,如果参数不符合要求,就不要跳转到B页面, 要求做一个 拦截
基础环境
json
"nuxt": "^3.11.2",
"vue": "^3.4.27",
"node": "v20.12.2"
代码
a页面代码
html
<template>
<div>
第一个页面,传参过去到b
<button @click="toPage">跳转</button>
</div>
</template>
<script setup>
const router = useRouter()
const toPage = () => {
router.push({
path: '/validate-route/b',
query: {
// 正常要传递一个数字,现在传递一个非数字
age: 'as'
}
})
.catch(err => {
console.log('捕获到的错误信息');
console.log(err);
})
}
</script>
b页面代码
html
<template>
<div>
<div>B页面</div>
</div>
</template>
<script setup>
definePageMeta({
validate: async (route) => {
if (!route.query.age) {
throw createError({ statusCode: 401, message: '没有传递age参数'})
}
let isNumber = /^\d+$/.test(route.query.age);
if (!isNumber) {
console.log('age不是数字');
// throw createError({ statusCode: 401, message: '参数验证不通过'})
// throw createError({ message: '参数验证不通过'})
return Promise.reject('是的,返回了一个Promise.reject 告诉你参数不通过')
} else {
// 正常情况
return true;
}
},
});
</script>
效果

页面仍旧是在 A页面, B页面也正确拦截到了, 错误消息我们也可以自行捕获并处理
官网文档
路由验证的官网文档,写的很隐晦, 翻译软件 翻译的中文意思是,"你可以返回一个xxx对象"
并没有对这个对象做限定

这里的对象,不是 普通对象,应该是Error 对象
我是根据TS 类型,才明白这里应该如何返回
- 我们去具体看看TS 类型定义,从ts 类型注释中可以看到,是这样定义的
typescript
validate?: (route: RouteLocationNormalized) => boolean | Partial<NuxtError> | Promise<boolean | Partial<NuxtError>>;
- 继续查看,NuxtError 是怎么定义类型的, 继承了 H3Error 这个对象
typescript
export interface NuxtError<DataT = unknown> extends H3Error<DataT> {
}
- 再继续看H3Error 类型
typescript
declare class H3Error<DataT = unknown> extends Error {
static __h3_error__: boolean;
statusCode: number;
fatal: boolean;
unhandled: boolean;
statusMessage?: string;
data?: DataT;
cause?: unknown;
constructor(message: string, opts?: {
cause?: unknown;
});
toJSON(): Pick<H3Error<DataT>, "data" | "statusCode" | "statusMessage" | "message">;
}
H3Error
又继承
了 Error 对象
, 所以,如果 validate 不返回一个 boolean类型, 就得返回一个 NuxtError 对象 或者一个 Promise<NuxtError>
小结
所以,上面的validate 可以返回如下的值
Promise<Boolean>
js
validate: () => {
if (不符合条件) {
return Promise.reject(false)
// 或者
return Promise.reject('是的,返回了一个Promise.reject 告诉你参数不通过')
}
}
boolean
js
validate: (route) => {
if (不符合条件) return false
return true
}
NuxtError
js
// 要携带这些信息
throw createError({ statusCode: 401, message: '参数验证不通过'})
// 没有状态码也是可以的
throw createError({ message: '随便写的参数'})
其他
为什么在A页面的router 的 catch 能捕获到错误?
vue-router的知识, 路由是异步的
scss
router.push()
router.replace()
返回的都是一个 Promise<.....>
