微信小程序未登录状态下的导航拦截有哪些方法可以实现
1. 全局路由拦截(最推荐)
原理:利用小程序页面栈和路由跳转机制进行统一拦截
实现步骤:
// app.js 中定义全局路由守卫
App({onLaunch() {// 存储原始路由方法const originalNavigateTo = wx.navigateTo;wx.navigateTo = function(options) {if (needAuth(options.url) && !isLogin()) {return redirectToLogin(); // 跳转到登录页}originalNavigateTo.call(this, options);};// 对 wx.redirectTo/wx.switchTab 等做同样处理}
})// 检查页面是否需要登录
function needAuth(url) {const authPages = ['/pages/order/order', '/pages/profile/profile'];return authPages.some(page => url.includes(page));
}
2. 页面跳转前检查(组件化方案)
原理:封装自定义导航组件
实现代码
// components/auth-navigate/auth-navigate.js
Component({methods: {handleNavigate() {if (this.data.requireAuth && !getApp().globalData.isLogin) {wx.navigateTo({ url: '/pages/login/login' });} else {wx.navigateTo({ url: this.data.target });}}}
})// 页面中使用
<auth-navigate target="/pages/order/order" require-authbindtap="handleNavigate"
>去订单页</auth-navigate>
3. 页面生命周期拦截
原理:在页面的onLoad
或onShow
中检查
实现代码:
// pages/order/order.js
Page({onShow() {if (!getApp().globalData.isLogin) {wx.redirectTo({ url: '/pages/login/login' });return;}// 正常逻辑...}
})
4. 后端接口拦截(补充方案)
原理:通过接口返回状态码强制跳转
实现逻辑
// 封装请求方法
function request(url, data) {return new Promise((resolve, reject) => {wx.request({url,success(res) {if (res.data.code === 401) { // 未登录状态码redirectToLogin();reject('未登录');} else {resolve(res.data);}}});});
}
5. 本地存储检查(简单方案)
原理:利用wx.getStorageSync
快速验证
实现代码:
function checkAuth() {try {const token = wx.getStorageSync('token');if (!token) throw new Error();} catch {wx.showModal({title: '提示',content: '请先登录',success() { wx.reLaunch({ url: '/pages/login/login' }) }});return false;}return true;
}
方案对比
方法 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
全局路由拦截 | 一劳永逸,维护成本低 | 需要处理特殊页面(如tabBar) | 中大型应用 |
自定义导航组件 | 组件化,可复用性强 | 每个链接需替换为组件 | 需要精细控制的场景 |
页面生命周期检查 | 实现简单 | 每个页面需单独添加代码 | 少量需要拦截的页面 |
后端接口拦截 | 权限控制绝对可靠 | 用户感知延迟 | 对安全性要求高的功能 |
本地存储检查 | 快速实现 | 无法防止直接URL访问 | 简单小程序 |
最佳实践建议
组合使用:
核心方案:全局路由拦截 + 页面生命周期检查
增强方案:关键接口401拦截
用户体验优化:
// 登录成功后返回原页面 wx.redirectTo({url: '/pages/login/login?redirect=' + encodeURIComponent(currentPage) });
特殊页面处理:
// 在app.js中排除登录页 if (options.url.includes('login')) {return originalNavigateTo.call(this, options); }
4.TabBar页面处理:
// 由于switchTab不能带参数,需使用全局变量
getApp().globalData.requireLogin = true;
wx.switchTab({ url: '/pages/profile/profile' });
注意事项
小程序页面路径最多支持10层,避免循环跳转
tabBar
页面无法通过navigateTo
跳转,需特殊处理在
onLaunch
中无法获取页面栈,建议用getCurrentPages()
做运行时检查
根据项目复杂度选择方案,一般推荐方案1+3的组合实现。