大家好,我是小杨,一个做了6年前端的老司机。今天我们来聊聊路由守卫这个在前端开发中特别实用的功能,它能帮我们控制页面的跳转流程,就像给网站请了个尽职的保安。
一、什么是路由守卫?
简单说,路由守卫就是页面跳转时的"安检门"。比如:
- 用户没登录想进会员中心?拦住!
- 页面数据没保存就想离开?弹窗提醒!
- 普通员工想访问管理员页面?门都没有!
二、Vue路由的三大守卫钩子
1. 全局守卫 - 整个网站的保安队长
javascript
// 全局前置守卫(每次跳转前都会触发)
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth && !我.store.state.isLogin) {
next('/login') // 去登录页
} else {
next() // 放行
}
})
// 全局解析守卫(适合做权限校验)
router.beforeResolve(async to => {
if (to.meta.requiresAdmin) {
await 我.checkAdminRole() // 异步检查权限
}
})
// 全局后置钩子(跳转完成后触发)
router.afterEach((to, from) => {
sendToAnalytics(to.fullPath) // 可以在这里做页面统计
})
2. 路由独享守卫 - 特定页面的专属安检
javascript
const routes = [
{
path: '/dashboard',
component: Dashboard,
beforeEnter: (to, from, next) => {
if (!我.store.state.userInfo.vip) {
next('/upgrade') // 非VIP跳转到升级页
} else {
next()
}
}
}
]
3. 组件内守卫 - 组件自己的小门卫
javascript
export default {
beforeRouteEnter(to, from, next) {
// 注意!这里还不能用this
next(vm => {
vm.initData() // 通过vm访问组件实例
})
},
beforeRouteUpdate(to, from, next) {
// 当前路由改变但组件被复用时触发
this.fetchData(to.params.id)
next()
},
beforeRouteLeave(to, from, next) {
if (this.hasUnsavedChanges) {
if (confirm('有未保存的修改,确定离开吗?')) {
next()
} else {
next(false) // 取消导航
}
} else {
next()
}
}
}
三、React路由守卫实现方案
React Router没有内置守卫,但我们可以自己实现:
1. 高阶组件方式
javascript
function PrivateRoute({ component: Component, ...rest }) {
return (
<Route
{...rest}
render={props =>
我.isAuthenticated ? (
<Component {...props} />
) : (
<Redirect to="/login" />
)
}
/>
)
}
2. 自定义Hook方式
javascript
function useAuthGuard() {
const history = useHistory()
useEffect(() => {
if (!我.store.getState().auth.isLogin) {
history.replace('/login')
}
}, [history])
}
// 在需要守卫的组件中使用
function AdminPage() {
useAuthGuard()
return <div>管理员页面</div>
}
四、实战中的骚操作
- 动态路由加载:在beforeEach中按需加载路由
javascript
router.beforeEach(async (to) => {
if (to.meta.requiresAdmin && !我.hasAdminRoute) {
await 我.loadAdminRoutes() // 动态添加路由
return to.fullPath // 重定向到目标页
}
})
- 页面离开确认:
javascript
beforeRouteLeave(to, from, next) {
window.onbeforeunload = () => "数据可能丢失!" // 浏览器原生提示
// ...其他逻辑
}
- 滚动行为控制:
javascript
router.afterEach((to) => {
if (to.meta.scrollToTop) {
window.scrollTo(0, 0)
}
})
五、常见坑点指南
- 死循环陷阱:
javascript
// 错误示范!会导致无限循环
router.beforeEach((to, from, next) => {
if (!isLogin) next('/login')
})
// 正确做法
router.beforeEach((to, from, next) => {
if (!isLogin && to.path !== '/login') next('/login')
else next()
})
- 异步操作处理:
javascript
// 记得要调用next!
beforeRouteEnter(to, from, next) {
fetchData().then(() => next()) // 别忘了next
}
- meta字段妙用:
javascript
{
path: '/admin',
meta: {
requiresAuth: true,
requiredRole: 'admin'
}
}
六、总结
路由守卫用得好,能帮我们实现:
- ✅ 登录状态验证
- ✅ 权限精细控制
- ✅ 数据变更提示
- ✅ 页面访问统计
- ✅ 动态路由加载
记住守卫钩子的执行顺序:全局beforeEach → 路由beforeEnter → 组件beforeRouteEnter → 全局beforeResolve → 全局afterEach
希望这篇能帮到大家!如果有问题欢迎在评论区交流,我会把6年踩过的坑都分享出来~
⭐ 写在最后
请大家不吝赐教,在下方评论或者私信我,十分感谢🙏🙏🙏.
✅ 认为我某个部分的设计过于繁琐,有更加简单或者更高逼格的封装方式
✅ 认为我部分代码过于老旧,可以提供新的API或最新语法
✅ 对于文章中部分内容不理解
✅ 解答我文章中一些疑问
✅ 认为某些交互,功能需要优化,发现BUG
✅ 想要添加新功能,对于整体的设计,外观有更好的建议
✅ 一起探讨技术加qq交流群:906392632
最后感谢各位的耐心观看,既然都到这了,点个 👍赞再走吧!