很多开发者可能都遇到过这样的场景:用户登录成功后跳转到首页,这时候如果用户不小心点击了左上角的返回按钮,就会退回到登录页面。这显然不符合业务逻辑——已经登录成功的用户,不应该还能返回到登录页。
我在实际项目中就踩过这个坑。当时我们的电商小程序上线后,客服经常收到用户反馈:"为什么我点返回又让我重新登录?"后来排查发现,就是因为没有处理好导航栏返回按钮的逻辑。这种体验上的小瑕疵,往往会让用户对产品的专业度产生怀疑。
微信小程序默认的页面栈管理机制,会让每个新页面自动带上返回按钮。这在大多数场景下是合理的,但在登录页、首页等关键节点,我们需要更精细的控制。这就是wx.reLaunch和wx.hideHomeButton这对组合出场的时候了。
微信小程序的页面栈就像一叠扑克牌,每次用wx.navigateTo跳转时,就像在最上面放一张新牌;用wx.navigateBack时,则是拿走最上面那张牌。而wx.reLaunch的特殊之处在于,它会清空整叠牌,然后放上你指定的那张。
举个例子:
这个特性非常适合登录场景。当用户从登录页跳转到首页时,如果用普通跳转,登录页会留在栈中;用reLaunch则能确保首页成为栈中唯一页面。
wx.hideHomeButton这个API有点特殊,它必须在页面的onShow生命周期中调用才有效。这是因为导航栏的渲染时机与页面生命周期密切相关。
我做过测试,如果在onLoad中调用,虽然不会报错,但实际不会生效。这是因为:
onLoad时导航栏可能还未完成初始化onShow才是确保操作生效的正确时机先来看登录页的关键代码。这个页面需要实现两个功能:
javascript复制// login.js
Page({
// 登录提交处理
async submitLogin() {
try {
const res = await wx.login() // 获取code
const { code } = await request('/api/login', { code: res.code })
if(code === 200) {
// 关键点:使用reLaunch跳转
wx.reLaunch({
url: '/pages/home/index'
})
}
} catch (error) {
wx.showToast({
title: '登录失败',
icon: 'none'
})
}
},
// 必须在这里调用hideHomeButton
onShow() {
wx.hideHomeButton()
}
})
对应的json配置:
json复制{
"navigationBarTitleText": "用户登录",
"navigationStyle": "default"
}
首页的逻辑与登录页类似,主要区别在于要处理退出登录的逻辑:
javascript复制// home.js
Page({
// 退出登录处理
handleLogout() {
wx.showModal({
title: '提示',
content: '确定要退出登录吗?',
success: (res) => {
if(res.confirm) {
// 同样使用reLaunch跳转
wx.reLaunch({
url: '/pages/login/index'
})
}
}
})
},
// 隐藏返回按钮
onShow() {
wx.hideHomeButton()
}
})
这个问题我被问过不下20次。最常见的原因有三个:
onShow中调用"navigationStyle": "custom"解决方案排查步骤:
"default"样式"requiredBackgroundModes": ["hideHomeButton"]有开发者反馈使用reLaunch后偶尔会出现短暂白屏。这是正常现象,因为reLaunch会销毁所有页面。优化方案有两种:
javascript复制wx.showLoading({
title: '加载中',
mask: true
})
setTimeout(() => {
wx.hideLoading()
}, 500)
javascript复制// app.js
App({
onLaunch() {
this.globalData.userInfo = wx.getStorageSync('userInfo')
}
})
有时我们既需要隐藏返回按钮,又需要自定义导航栏样式。这时可以这样配合使用:
json复制{
"navigationBarTitleText": "首页",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
然后在页面的wxml中添加自定义导航栏组件,同时在js中仍然调用hideHomeButton来处理系统返回按钮。
对于复杂的页面流,我的经验是:
例如电商小程序的典型流程:
code复制登录 → reLaunch首页 → navigateTo商品列表 → navigateTo商品详情 → redirectTo订单确认
这种组合既能保证关键页面不被意外返回,又能保持合理的页面栈深度。