各位靓仔靓女,晚上好!我是你们的老朋友,今天咱们聊聊 Nuxt.js 里让人又爱又恨的 middleware
(中间件)。
这玩意儿,说它简单吧,几行代码就能搞定;说它复杂吧,一不留神执行顺序就乱了套,权限验证直接失效,用户体验瞬间爆炸。所以,今天咱们就来好好扒一扒它的底裤,看看它到底是怎么工作的。
开场白:中间件是啥?能吃吗?
简单来说,中间件就像你家门卫大爷,每个请求都要经过他老人家过一遍。他可以检查你有没有带钥匙,是不是业主,有没有携带危险物品等等。Nuxt.js 的中间件就是干这些活儿的,可以在请求到达你的页面组件之前,或者渲染页面之前,做一些预处理。
中间件的种类:五花八门,总有一款适合你
Nuxt.js 提供了几种不同类型的中间件,它们的作用域和执行时机各不相同。咱们先来盘点一下:
-
全局中间件 (plugins/):
- 位置:
plugins/
目录下的.js
或.ts
文件。 - 作用域:整个应用。每个路由都会执行。
- 特点:需要在
nuxt.config.js
的plugins
数组中注册。 - 用途:比如:全局的权限检查,统计分析,第三方库初始化等等。
- 位置:
-
路由中间件 (middleware/):
- 位置:
middleware/
目录下。 - 作用域:可以用于特定路由或者页面组件。
- 特点:需要在
nuxt.config.js
的router.middleware
对象中注册 (命名路由中间件)。也可以直接在页面组件中使用 (匿名路由中间件)。 - 用途:权限验证,根据路由参数进行数据预取等等。
- 位置:
-
页面中间件 (在页面组件内定义):
- 位置:直接在
*.vue
页面组件的middleware
属性中定义。 - 作用域:只对当前页面组件有效。
- 特点:最简单直接,但复用性较差。
- 用途:只对当前页面有效的特殊处理。
- 位置:直接在
-
布局中间件 (在布局组件内定义):
- 位置:直接在
layouts/*.vue
布局组件的middleware
属性中定义。 - 作用域:只对使用该布局的页面组件有效。
- 特点:可以用于布局级别的权限控制或者数据预取。
- 用途:特定布局下的权限验证或数据获取。
- 位置:直接在
执行顺序:不按套路出牌?
这才是 middleware
最让人头疼的地方!如果你不了解它的执行顺序,很容易就会踩坑。
一般来说,middleware
的执行顺序如下(从上到下,先执行的在上面):
nuxt.config.js
中的modules
(模块) 执行的中间件。(模块可以注册全局中间件)layouts/*.vue
中定义的 布局中间件 (Layout Middleware)*.vue
页面组件中定义的 页面中间件 (Page Middleware)middleware/
目录下的 命名路由中间件 (Named Route Middleware)。通过nuxt.config.js
的router.middleware
注册,并在*.vue
组件中通过middleware: 'middleware-name'
使用。middleware/
目录下的 匿名路由中间件 (Anonymous Route Middleware)。在*.vue
组件中直接使用middleware: [function(){}]
。- 全局中间件 (Global Middleware)。
plugins/
目录下的.js
或.ts
文件,需要在nuxt.config.js
的plugins
数组中注册。
注意:
- 同类型的中间件,按照其定义顺序执行。
- 如果多个页面使用同一个布局,布局中间件只会执行一次。
- 如果路由匹配到多个页面组件,每个页面组件的中间件都会执行。
代码示例:用代码说话,胜过千言万语
咱们来写几个例子,看看 middleware
到底是怎么跑的。
1. 全局中间件 (plugins/auth.js)
// plugins/auth.js
export default function ({ store, redirect, route }) {
if (route.path !== '/login' && !store.state.auth.loggedIn) {
console.log('全局中间件:未登录,跳转到登录页');
return redirect('/login');
}
}
// nuxt.config.js
export default {
plugins: [
'~/plugins/auth' // 注册全局中间件
]
}
这个中间件会检查用户是否登录,如果未登录,并且访问的不是登录页,则跳转到登录页。
2. 路由中间件 (middleware/admin.js)
// middleware/admin.js
export default function ({ store, redirect }) {
if (!store.state.auth.user.isAdmin) {
console.log('路由中间件:不是管理员,禁止访问');
return redirect('/');
}
}
// nuxt.config.js
export default {
router: {
middleware: ['auth'] // 注册 auth 中间件
}
}
这个中间件会检查用户是否是管理员,如果不是,则跳转到首页。
3. 页面中间件 (pages/admin/index.vue)
<template>
<div>
<h1>Admin Page</h1>
</div>
</template>
<script>
export default {
middleware: ['admin'], // 使用 admin 路由中间件
mounted() {
console.log('页面组件:Admin Page mounted');
}
}
</script>
这个页面组件使用了 admin
路由中间件,只有管理员才能访问。
4. 匿名路由中间件 (pages/secret.vue)
<template>
<div>
<h1>Secret Page</h1>
</div>
</template>
<script>
export default {
middleware: [
function ({ store, redirect }) {
if (!store.state.auth.hasSecret) {
console.log('匿名路由中间件:没有权限访问');
return redirect('/');
}
}
],
mounted() {
console.log('页面组件:Secret Page mounted');
}
}
</script>
这个页面组件使用了匿名路由中间件,只有拥有 secret
权限的用户才能访问。
5. 布局中间件 (layouts/default.vue)
<template>
<div>
<Nuxt />
</div>
</template>
<script>
export default {
middleware: [
function ({ store, redirect }) {
if (store.state.auth.isBanned) {
console.log('布局中间件:用户被封禁,禁止访问');
return redirect('/banned');
}
}
]
}
</script>
这个布局中间件会检查用户是否被封禁,如果是,则跳转到 /banned
页面。所有使用 default
布局的页面都会受到这个中间件的影响。
作用域:你的地盘你做主
middleware
的作用域非常重要。它决定了哪些页面会受到中间件的影响。
- 全局中间件:影响整个应用,所有路由都会执行。
- 路由中间件:影响指定的路由或者页面组件。
- 页面中间件:只影响当前页面组件。
- 布局中间件:影响所有使用该布局的页面组件。
常见坑点:避坑指南,保你平安
- 执行顺序混乱:一定要搞清楚不同类型中间件的执行顺序,避免出现权限验证失效等问题。
- 异步操作:
middleware
函数必须返回Promise
或者使用async/await
处理异步操作,否则可能会导致程序出错。 - 过度使用:不要滥用
middleware
,只在必要的时候才使用。过多的middleware
会影响性能。 - 循环重定向:避免出现循环重定向的情况,比如 A 页面重定向到 B 页面,B 页面又重定向到 A 页面。
进阶技巧:让你的中间件更上一层楼
- 使用
async/await
:使用async/await
可以让你的middleware
代码更加简洁易懂。 - 使用
try/catch
:使用try/catch
可以捕获middleware
中出现的错误,避免程序崩溃。 - 使用
store
:middleware
可以访问store
,可以根据store
中的数据进行判断。 - 使用
route
:middleware
可以访问route
,可以根据路由参数进行判断。 - 使用
context
对象:middleware
函数接收一个context
对象,包含了store
、route
、redirect
、app
等属性,可以方便地访问 Nuxt.js 的各种功能。
表格总结:一图胜千言
中间件类型 | 位置 | 作用域 | 执行时机 | 如何使用 | 适用场景 |
---|---|---|---|---|---|
全局中间件 | plugins/ |
整个应用 | 每个路由 | 在 plugins/ 目录下创建 .js 或 .ts 文件,并在 nuxt.config.js 的 plugins 数组中注册。 |
全局的权限检查,统计分析,第三方库初始化等。 |
路由中间件 | middleware/ |
特定路由或页面组件 | 路由匹配到页面组件之前 | 在 middleware/ 目录下创建 .js 或 .ts 文件,并在 nuxt.config.js 的 router.middleware 对象中注册 (命名路由中间件)。也可以直接在页面组件中使用 middleware: [function(){}] (匿名路由中间件)。 |
权限验证,根据路由参数进行数据预取等。 |
页面中间件 | *.vue 页面组件内 |
当前页面组件 | 页面组件渲染之前 | 在 *.vue 页面组件的 middleware 属性中定义。 |
只对当前页面有效的特殊处理。 |
布局中间件 | layouts/*.vue 布局组件内 |
使用该布局的页面组件 | 页面组件使用该布局时渲染之前 | 在 layouts/*.vue 布局组件的 middleware 属性中定义。 |
特定布局下的权限验证或数据获取。 |
总结:掌握中间件,走向人生巅峰
middleware
是 Nuxt.js 中非常重要的一个概念,掌握它可以让你更好地控制应用的流程,实现更复杂的功能。希望今天的讲解能够帮助你更好地理解 middleware
的执行顺序和作用域,避开常见的坑点,写出更健壮、更高效的 Nuxt.js 应用。
最后,记住一点:多写代码,多调试,才能真正掌握 middleware
的精髓!
散会!