uni-router v1.7.0重磅更新:守卫重定向自由掌控

v1.7.0 为守卫的 next() 回调新增可选 options 参数,支持在重定向时显式指定导航方式(push / replace / relaunch),不再被原始导航方式绑定

前言

在 v1.7.0 之前,守卫中调用 next(location) 重定向时,跳转方式完全由"触发守卫的那次导航方法"决定:router.push 触发的守卫重定向时仍用 uni.navigateTorouter.replace 触发的则用 uni.redirectTo

这意味着一个常见场景无法实现:无论用户是从 push 还是 replace 进入受保护页面,未登录时都希望用 replace 跳转登录页,避免登录页之后残留多余的历史页面。v1.7.0 解决了这一限制。


一、问题分析

旧版行为

守卫的 next() 回调签名是:

typescript 复制代码
type NavigationGuardNext = (to?: RouteLocationRaw | false) => void

handleGuardResult 中重定向时直接透传原始 mode

typescript 复制代码
// router/index.ts(v1.6.3)
if (result.redirect) {
    const redirectTarget = this.matcher.resolve(result.redirect)
    return this.executeNavigation(redirectTarget, from, mode, redirectDepth + 1, ...)
    //                                                       ^^^^ 原始 mode 被沿用
}
触发导航 重定向实际调用
router.push uni.navigateTo
router.replace uni.redirectTo
router.relaunch uni.reLaunch
router.back 落入 else 分支 → uni.reLaunch

使用者在守卫内无法单独指定重定向方式。


二、新增能力

1. 扩展 next() 签名

typescript 复制代码
type NavigationGuardNext = (
    to?: RouteLocationRaw | false,
    options?: NavigationGuardNextOptions
) => void

interface NavigationGuardNextOptions {
    mode?: NavigationRedirectMode
}

type NavigationRedirectMode = 'push' | 'replace' | 'relaunch'

options.mode 仅在 next(location) 重定向时生效,对 next()next(false) 无影响。

2. 重定向方式优先级

typescript 复制代码
// router/index.ts(v1.7.0)
const redirectMode = result.mode ?? (mode === 'back' ? 'relaunch' : mode)
  • 守卫指定优先next(location, { mode: 'replace' }) 显式指定时使用 replace
  • 未指定则沿用原始next(location) 时沿用触发守卫的原始导航方式(向后兼容)
  • back 回退 relaunch :原始导航为 back 时,未指定 mode 则回退为 relaunch(因 back 无法跳转到页面栈外目标,保持 v1.6.3 的实际语义)

三、使用示例

场景一:登录拦截统一用 replace

最典型的应用场景。无论用户从哪种导航方式进入受保护页面,未登录时都强制用 replace 跳转登录页,避免登录后返回时出现受保护页面的残留历史:

typescript 复制代码
router.beforeEach((to, from, next) => {
    if (to.meta.requireAuth && !isLoggedIn()) {
        // ✅ 强制 replace,登录页之后不会残留受保护页面的历史
        next({ name: 'login', query: { redirect: to.fullPath } }, { mode: 'replace' })
    } else {
        next()
    }
})

对比旧版:

typescript 复制代码
// ❌ 旧版无法控制,重定向方式由触发守卫的导航决定
router.beforeEach((to, from, next) => {
    if (to.meta.requireAuth && !isLoggedIn()) {
        next({ name: 'login', query: { redirect: to.fullPath } })
        // 若用户通过 router.push 进入,重定向会用 navigateTo,登录页之后会残留受保护页面
    } else {
        next()
    }
})

场景二:退出登录后重置页面栈

退出登录后通常希望清空整个页面栈再跳转登录页,避免用户通过返回键回到已退出登录的页面:

typescript 复制代码
router.beforeEach((to, from, next) => {
    if (to.meta.requireAuth && !isLoggedIn()) {
        // ✅ 强制 relaunch,关闭所有页面后打开登录页
        next({ name: 'login' }, { mode: 'relaunch' })
    } else {
        next()
    }
})

场景三:保持原有行为(向后兼容)

不传 options 时行为与 v1.6.3 完全一致,现有代码无需任何修改:

typescript 复制代码
router.beforeEach((to, from, next) => {
    if (to.meta.requireAuth && !isLoggedIn()) {
        next({ name: 'login', query: { redirect: to.fullPath } })
        // 沿用原始导航方式,与 v1.6.3 行为一致
    } else {
        next()
    }
})

四、mode 取值对照

对应方法 uni API 说明
'push' router.push() uni.navigateTo 保留当前页面,跳转到新页面
'replace' router.replace() uni.redirectTo 关闭当前页面,跳转到新页面
'relaunch' router.relaunch() uni.reLaunch 关闭所有页面,打开新页面

::: tip 注意事项

  • 重定向方式仅影响跳转 API 的选择,守卫链、动画、事件等行为保持一致
  • mode 仅在 next(location) 重定向时生效,对 next()next(false) 无影响
  • 重定向仍会触发新的导航流程(重新执行所有守卫),最大重定向深度仍为 10 次 :::

升级指南

v1.7.0 是完全向后兼容的新功能版本,无需修改任何现有代码即可升级。

行为变化

场景 v1.6.3 及之前 v1.7.0
next(location) 沿用原始导航方式 沿用原始导航方式(无变化)
next(location, { mode }) 不支持 使用指定的 mode 重定向
back 触发的重定向 实际走 relaunch 未指定 mode 时仍回退 relaunch(无变化)
其他导航方式触发的重定向 沿用原始方式 未指定 mode 时沿用原始方式(无变化)

新增类型导出

  • NavigationGuardNextOptions --- next() 回调的可选参数类型
  • NavigationRedirectMode --- 重定向方式类型('push' | 'replace' | 'relaunch'
相关推荐
小心我捶你啊32 分钟前
数据采集和Web解锁不是一回事,从用途到规则区分
前端·爬虫·网络协议
hunterandroid1 小时前
[鸿蒙从零到一] ArkUI 基础组件实战:Text、Image、Button 与 TextInput
前端
fsssb1 小时前
Chromium 源码学习笔记(五):一次点击,在进入 JS 之前先经历了什么?
前端
hunterandroid1 小时前
WorkManager 可靠性实战:唯一任务、重试与幂等设计
android·前端
鹿目1 小时前
使用 Vant CLI 搭建 UI 组件库:从 H5 到小程序跨平台
前端·javascript
默_笙1 小时前
😭 我花了两小时找了一个数据结构 bug,才把"迷你 Cursor"跑起来,绝望(bushi)
前端·javascript
竹林8181 小时前
wagmi v2 监听合约事件踩坑记:从 `useContractEvent` 到 `watchContractEvent`,我重构了三版才搞定实时数据流
前端·javascript
天若有情6732 小时前
纯HTML+Tailwind单页作品集网站——零框架静态前端完整源码
前端·html
WebGirl2 小时前
H5唤起app前端实现方案
前端
heimeiyingwang2 小时前
【架构实战】SQL注入与XSS防御:常见Web漏洞的系统性修复
前端·sql·架构