Nuxt.js中间件使用
学习目标
通过本章节的学习,你将能够:
- 了解Nuxt.js中间件的基本概念
- 掌握中间件的创建和注册方法
- 了解中间件的执行顺序
- 学习全局中间件和页面中间件的区别
- 掌握路由守卫的实现方法
- 了解中间件的应用场景
核心知识点讲解
中间件的基本概念
在Nuxt.js中,中间件是在页面渲染之前执行的函数。通过中间件,你可以:
- 验证用户身份
- 权限控制
- 数据预处理
- 路由重定向
- 日志记录
中间件的创建和注册
创建中间件文件
中间件文件存放在middleware目录中:
├── middleware/
│ ├── auth.js # 认证中间件
│ ├── logger.js # 日志中间件
│ └── redirect.js # 重定向中间件基本中间件结构
// middleware/auth.js
export default function ({ store, route, redirect, error }) {
// 检查用户是否已登录
const isAuthenticated = store.state.user.loggedIn
// 如果用户未登录且访问的是需要认证的页面,则重定向到登录页
if (!isAuthenticated && route.path.startsWith('/admin')) {
return redirect('/login')
}
// 如果用户已登录但访问的是登录页,则重定向到首页
if (isAuthenticated && route.path === '/login') {
return redirect('/')
}
}注册中间件
全局中间件
在nuxt.config.js中注册全局中间件:
// nuxt.config.js
module.exports = {
router: {
middleware: 'auth' // 全局应用auth中间件
}
}页面中间件
在页面组件中注册中间件:
<!-- pages/admin/index.vue -->
<template>
<div>
<h1>管理后台</h1>
</div>
</template>
<script>
export default {
middleware: 'auth' // 仅在当前页面应用auth中间件
}
</script>布局中间件
在布局组件中注册中间件:
<!-- layouts/admin.vue -->
<template>
<div class="admin-layout">
<!-- 布局内容 -->
</div>
</template>
<script>
export default {
middleware: 'auth' // 在使用此布局的所有页面应用auth中间件
}
</script>中间件的执行顺序
Nuxt.js中间件的执行顺序如下:
- nuxt.config.js 中定义的全局中间件
- 布局组件 中定义的中间件
- 页面组件 中定义的中间件
如果多个中间件需要按特定顺序执行,可以在页面组件中使用数组形式指定:
<!-- pages/admin/users.vue -->
<template>
<div>
<h1>用户管理</h1>
</div>
</template>
<script>
export default {
middleware: ['auth', 'admin'] // 先执行auth中间件,再执行admin中间件
}
</script>全局中间件vs页面中间件
全局中间件
- 在
nuxt.config.js中注册 - 应用于所有页面
- 适用于需要全局处理的逻辑(如日志记录、基本认证等)
页面中间件
- 在页面或布局组件中注册
- 仅应用于特定页面或使用特定布局的页面
- 适用于需要特定页面处理的逻辑(如页面权限控制、数据预处理等)
路由守卫实现
Nuxt.js中间件可以实现类似Vue Router的路由守卫功能:
全局前置守卫
// middleware/global.js
export default function ({ route, from, store }) {
console.log('全局中间件执行')
console.log('当前路由:', route.path)
console.log('来源路由:', from ? from.path : '无')
// 可以在这里执行全局路由逻辑
}路由独享守卫
// middleware/admin.js
export default function ({ store, redirect }) {
// 检查用户是否为管理员
const isAdmin = store.state.user.role === 'admin'
if (!isAdmin) {
return redirect('/403')
}
}组件内守卫
在Nuxt.js中,可以在页面组件的middleware属性中直接定义函数:
<!-- pages/profile.vue -->
<template>
<div>
<h1>用户资料</h1>
</div>
</template>
<script>
export default {
middleware({ store, route, redirect }) {
// 组件内守卫逻辑
const isAuthenticated = store.state.user.loggedIn
if (!isAuthenticated) {
return redirect('/login')
}
}
}
</script>中间件的高级用法
异步中间件
// middleware/fetch-data.js
export default async function ({ store, route }) {
// 异步获取数据
await store.dispatch('fetchData', route.params.id)
// 数据获取完成后继续渲染页面
}动态中间件
<!-- pages/[id].vue -->
<template>
<div>
<h1>动态页面</h1>
</div>
</template>
<script>
export default {
middleware({ route }) {
// 根据路由参数动态选择中间件
if (route.params.id === 'admin') {
return 'admin'
} else {
return 'auth'
}
}
}
</script>中间件应用场景
认证和授权:
- 检查用户是否已登录
- 验证用户权限
- 保护敏感页面
数据预处理:
- 在页面渲染前获取必要的数据
- 验证路由参数
- 准备页面所需的状态
路由控制:
- 路由重定向
- 路由拦截
- 404处理
性能监控:
- 记录页面加载时间
- 监控API调用
- 错误跟踪
国际化:
- 根据用户语言设置重定向
- 加载对应语言的资源
实用案例分析
案例一:认证中间件
场景:在项目中实现用户认证,保护需要登录才能访问的页面。
解决方案:
// middleware/auth.js
export default function ({ store, route, redirect, app }) {
// 白名单路由,不需要认证
const whiteList = ['/login', '/register', '/404', '/500']
// 检查当前路由是否在白名单中
const isInWhiteList = whiteList.includes(route.path)
// 检查用户是否已登录
const isAuthenticated = store.state.user.loggedIn
// 如果用户未登录且不在白名单中,则重定向到登录页
if (!isAuthenticated && !isInWhiteList) {
// 保存当前路由,登录后可重定向回该页面
store.commit('user/setRedirectPath', route.fullPath)
return redirect('/login')
}
// 如果用户已登录但在登录页,则重定向到首页或之前保存的页面
if (isAuthenticated && route.path === '/login') {
const redirectPath = store.state.user.redirectPath || '/'
store.commit('user/setRedirectPath', '')
return redirect(redirectPath)
}
}使用方法:
// nuxt.config.js
module.exports = {
router: {
middleware: 'auth' // 全局应用auth中间件
}
}<!-- pages/login.vue -->
<template>
<div class="login-page">
<h1>登录</h1>
<form @submit.prevent="handleLogin">
<div>
<label>用户名</label>
<input v-model="form.username" type="text" required>
</div>
<div>
<label>密码</label>
<input v-model="form.password" type="password" required>
</div>
<button type="submit">登录</button>
</form>
</div>
</template>
<script>
export default {
data() {
return {
form: {
username: '',
password: ''
}
}
},
methods: {
async handleLogin() {
try {
// 登录逻辑
await this.$store.dispatch('user/login', this.form)
// 登录成功后,中间件会自动重定向
} catch (error) {
console.error('登录失败:', error)
}
}
}
}
</script>案例二:权限控制中间件
场景:在管理后台中实现基于角色的权限控制,确保不同角色只能访问对应的页面。
解决方案:
// middleware/permission.js
// 定义路由权限映射
const permissionMap = {
'/admin/dashboard': ['admin', 'editor'],
'/admin/users': ['admin'],
'/admin/products': ['admin', 'editor'],
'/admin/settings': ['admin']
}
export default function ({ store, route, redirect }) {
// 检查用户是否已登录
const isAuthenticated = store.state.user.loggedIn
if (!isAuthenticated) {
return redirect('/login')
}
// 获取用户角色
const userRole = store.state.user.role
// 检查当前路由是否需要权限
const requiredRoles = permissionMap[route.path]
// 如果路由需要权限且用户角色不在允许列表中,则重定向到403页面
if (requiredRoles && !requiredRoles.includes(userRole)) {
return redirect('/403')
}
}使用方法:
<!-- pages/admin/users.vue -->
<template>
<div>
<h1>用户管理</h1>
</div>
</template>
<script>
export default {
middleware: ['auth', 'permission'] // 先执行认证中间件,再执行权限中间件
}
</script>案例三:日志中间件
场景:在项目中实现访问日志记录,记录用户的访问行为。
解决方案:
// middleware/logger.js
export default function ({ route, from, req, res }) {
// 获取客户端IP
const clientIP = req ? req.connection.remoteAddress : 'localhost'
// 获取用户代理
const userAgent = req ? req.headers['user-agent'] : navigator.userAgent
// 构建日志信息
const logInfo = {
timestamp: new Date().toISOString(),
path: route.path,
from: from ? from.path : 'null',
ip: clientIP,
userAgent: userAgent
}
// 打印日志
console.log('访问日志:', logInfo)
// 可以将日志保存到数据库或日志文件
// saveLog(logInfo)
}使用方法:
// nuxt.config.js
module.exports = {
router: {
middleware: 'logger' // 全局应用logger中间件
}
}案例四:国际化中间件
场景:在项目中实现国际化,根据用户的语言设置或路由参数切换语言。
解决方案:
// middleware/i18n.js
export default function ({ store, route, redirect, app }) {
// 从路由参数获取语言
const langFromRoute = route.params.lang
// 支持的语言列表
const supportedLanguages = ['zh', 'en']
// 如果路由参数中有语言且在支持列表中,则设置语言
if (langFromRoute && supportedLanguages.includes(langFromRoute)) {
store.commit('i18n/setLocale', langFromRoute)
app.i18n.locale = langFromRoute
}
// 如果路由参数中有语言但不在支持列表中,则重定向到默认语言
else if (langFromRoute && !supportedLanguages.includes(langFromRoute)) {
return redirect('/zh' + route.path.replace(`/${langFromRoute}`, ''))
}
// 如果路由参数中没有语言,则使用默认语言
else {
const defaultLang = 'zh'
if (!route.path.startsWith(`/${defaultLang}`)) {
return redirect(`/${defaultLang}${route.path}`)
}
}
}使用方法:
// nuxt.config.js
module.exports = {
router: {
middleware: 'i18n' // 全局应用i18n中间件
}
}<!-- pages/[lang]/index.vue -->
<template>
<div>
<h1>{{ $t('home.title') }}</h1>
<p>{{ $t('home.description') }}</p>
<div class="language-switcher">
<nuxt-link to="/zh">中文</nuxt-link>
<nuxt-link to="/en">English</nuxt-link>
</div>
</div>
</template>
<script>
export default {
// 中间件已在全局注册
}
</script>总结
本章节详细介绍了Nuxt.js的中间件使用,包括:
- 中间件的基本概念:中间件的作用和优势
- 中间件的创建和注册:如何创建中间件文件以及在不同位置注册中间件
- 中间件的执行顺序:全局中间件、布局中间件和页面中间件的执行顺序
- 全局中间件vs页面中间件:两种中间件的区别和使用场景
- 路由守卫实现:如何使用中间件实现路由守卫功能
- 中间件的高级用法:异步中间件和动态中间件
- 中间件应用场景:认证和授权、数据预处理、路由控制、性能监控和国际化
通过合理使用中间件,可以实现复杂的业务逻辑,提高应用的安全性和可维护性。在实际项目中,应根据具体需求选择合适的中间件类型,并遵循最佳实践,确保中间件的可靠性和性能。
练习
- 创建一个Nuxt.js项目,添加认证中间件
- 实现基于角色的权限控制中间件
- 创建日志中间件,记录用户访问行为
- 实现国际化中间件,支持多语言切换
- 测试不同中间件的执行顺序