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-auth
bindtap="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的组合实现。