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'
相关推荐
逸铭1 小时前
Day 4:登录与 Token——桌面端怎么存密钥
前端·客户端
溯朢1 小时前
TokUI 流式渲染的 SSE 全链路拆解
前端
京东云开发者1 小时前
京东 Oxygen xLLM 大模型推理引擎正式捐赠开放原子开源基金会,共建国产 AI Infra 生态
前端
Csvn1 小时前
LLM 一把梭:从 Swagger 文档到类型安全 API 请求,再也不手写接口
前端
DGT1 小时前
深入理解 JavaScript 闭包
前端
星栈1 小时前
Dioxus 表单处理:从输入、校验到文件上传,一条链路讲透
前端·rust·前端框架
用户41659673693551 小时前
WebView 请求异常排查操作手册
android·前端
weedsfly1 小时前
JavaScript 事件流:彻底搞懂捕获、冒泡与事件委托
前端·javascript·react.js
RainmeoX1 小时前
【实战】用纯前端打造绝区零风格 AI 角色助手 WebUI 并联调 vLLM
前端