uni-router v1.6.0重磅更新:安全传参新姿势

v1.6.0 新增 params 页面参数传递、参数持久化存储、查询参数增强方法,修复导航解析阶段 params 丢失问题

前言

uni-app 的页面间数据传递一直是个痛点。query 参数只能传字符串,复杂数据需要手动 JSON.stringify/parse,且暴露在 URL 中不安全;uni.setStorageSync 虽然能存复杂数据,但需要手动管理生命周期,容易遗漏清理。

v1.6.0 引入 params 机制,让页面间传递复杂数据变得像 query 一样简单,同时不暴露在 URL 中。配合 queryInt / queryNumber / queryBool 查询参数增强方法,uni-router 的数据传递能力更加完整。


一、页面参数传递(params)

为什么需要 params?

uni-app 的 query 参数存在两个限制:

  1. 仅支持字符串router.push({ path: '/pages/detail', query: { price: 19.99 } }) 中的 price 在目标页面读取时是字符串 '19.99',需要手动转换
  2. 暴露在 URL 中:敏感数据(如用户信息、订单详情)不适合放在 query 中

params 解决了这两个问题:支持传递任意 JSON 可序列化数据(对象、数组、嵌套结构),且不暴露在 URL 中。

基本用法

发起导航 — 传入 params

await router.push({
	path: '/pages/detail/index',
	query: { id: 'order-001' }, // query 仍用于 URL 可见参数
	params: {
		// params 不暴露在 URL 中
		userInfo: { name: 'Tom', age: 20 },
		tags: ['vip', 'active'],
		orderDetail: { items: [{ name: '商品A', qty: 2 }], total: 199.9 }
	}
})

目标页面 — 读取 params

import { useRoute } from '@meng-xi/uni-router'

const route = useRoute()

// route.value.params 是只读对象
console.log(route.value.params.userInfo) // { name: 'Tom', age: 20 }
console.log(route.value.params.tags) // ['vip', 'active']

params 类型定义

// 页面参数值类型 — 支持 JSON 可序列化数据
type ParamValue = string | number | boolean | null | ParamValue[] | { [key: string]: ParamValue }

// 页面参数对象
interface ParamObject {
	[key: string]: ParamValue
}

// RouteLocation 中的 params 字段
interface RouteLocation {
	// ...
	params: Readonly<ParamObject>
}

params 与 query 的区别

特性 query params
URL 可见
数据类型 仅字符串(Record<string, string> 任意 JSON 可序列化数据
刷新保留 是(H5) 否(默认),开启 persistent 后是
适用场景 页面标识、简单筛选 复杂数据传递、敏感信息

二、参数持久化存储(persistent)

为什么需要持久化?

默认情况下,params 存储在内存中。在 H5 平台上,用户刷新页面后内存数据丢失,route.params 将为空对象。persistent 选项将 params 持久化到 uni.setStorageSync,刷新后仍可读取。

单次导航持久化

await router.push({
	path: '/pages/detail/index',
	query: { id: 'persistent-demo' },
	params: { bigData: { items: [1, 2, 3], total: 3 } },
	persistent: true // 此次的 params 持久化到 storage
})

全局默认持久化

通过 paramsPersistent 配置项设置全局默认值,避免每次导航都手动指定:

const router = createRouter({
	routes,
	paramsPersistent: true // 所有 params 默认持久化
})

// 单次导航可通过 persistent 覆盖全局默认值
await router.push({
	path: '/pages/detail/index',
	params: { tempData: '不需要持久化' },
	persistent: false // 覆盖全局默认值,此次不持久化
})

持久化原理

  • persistent: true 时,params 同时写入内存 Map 和 uni.setStorageSync
  • persistent: false(默认)时,params 仅写入内存 Map
  • 读取时优先从内存获取,内存未命中再从 storage 读取
  • 路由器在 syncRoute() 时自动清理不再需要的 params(通过 cleanupStale() 惰性清理)

三、查询参数增强方法

问题背景

uni-app 的 query 参数始终是字符串类型。即使传入 router.push({ query: { price: 19.99, enabled: true } }),在目标页面读取时也是 '19.99''true',需要手动转换:

// 没有增强方法时的写法
const price = Number(route.value.query.price) || 0
const enabled = route.value.query.enabled === 'true'

queryInt / queryNumber / queryBool

v1.6.0 为 RouteLocation 新增三个便捷方法,自动完成类型转换:

const route = useRoute()

// queryInt — 解析为整数
const id = route.value.queryInt('id') // '42' → 42
const page = route.value.queryInt('page', 1) // 缺失时返回默认值 1

// queryNumber — 解析为数值(支持浮点)
const price = route.value.queryNumber('price') // '19.99' → 19.99
const total = route.value.queryNumber('total', 0) // 缺失时返回默认值 0

// queryBool — 解析为布尔值
const enabled = route.value.queryBool('enabled') // 'true' → true, '1' → true
const visible = route.value.queryBool('visible', true) // 缺失时返回默认值 true

方法签名

interface RouteLocation {
	// ...
	queryInt(key: string, defaultValue?: number): number | undefined
	queryNumber(key: string, defaultValue?: number): number | undefined
	queryBool(key: string, defaultValue?: boolean): boolean | undefined
}

解析规则

方法 输入 输出 说明
queryInt '42' 42 使用 parseInt 解析
queryInt '3.14' 3 截断小数部分
queryInt 'abc' defaultValue 解析失败返回默认值
queryNumber '19.99' 19.99 使用 parseFloat 解析
queryNumber 'abc' defaultValue 解析失败返回默认值
queryBool 'true' / '1' true 识别为 true 的值
queryBool 'false' / '0' false 识别为 false 的值
queryBool 'yes' defaultValue 无法识别返回默认值

声明式导航组件 RouterLink 同步支持 paramspersistent

<template>
	<!-- 带 params 跳转 -->
	<mxuni-router :to="{ path: '/pages/detail/index', query: { id: 'link-params' } }" :params="{ orderInfo: { orderId: 'A001', amount: 99.9 } }">
		<view class="btn">查看订单详情</view>
	</mxuni-router>

	<!-- params 持久化 -->
	<mxuni-router :to="{ path: '/pages/detail/index', query: { id: 'link-persistent' } }" :params="{ config: { theme: 'dark' } }" persistent>
		<view class="btn">查看配置(刷新后仍可读取)</view>
	</mxuni-router>
</template>

新增 Props

Prop 类型 默认值 说明
params ParamObject undefined 页面参数,支持复杂数据(仅 JSON 可序列化值),不暴露在 URL 中
persistent boolean undefined 页面参数是否持久化到 storage,H5 刷新后仍可读取

五、RouterOptions 新增 paramsPersistent

选项 类型 默认值 说明
paramsPersistent boolean false 页面参数持久化默认值,设为 true 时所有 params 默认通过 uni.setStorageSync 持久化存储,H5 刷新后仍可读取,单次导航可通过 persistent 选项覆盖

六、RouteLocationPathRaw / RouteLocationNamedRaw 新增字段

字段 类型 默认值 说明
params ParamObject undefined 页面参数,支持复杂数据(仅 JSON 可序列化值),不暴露在 URL 中
persistent boolean undefined 页面参数是否持久化到 storage,H5 刷新后仍可读取

七、Bug 修复

paramsManager.get() 惰性清理导致导航时 params 丢失

问题:使用 params 跳转到目标页面时,route.params 为空对象 {}

根因paramsManager.get() 在读取 params 时会执行惰性清理——检查当前页面栈中是否还有页面在使用该 params key,如果没有则删除。但在 matcher.resolve() 阶段(导航执行前),目标页面尚未入栈,导致 params 被误删并返回
undefined

修复

  1. 新增 peek() 方法——读取 params 但不做惰性清理
  2. extractParamssyncCurrentRoute 改用 peek 读取 params
  3. syncRoute() 中通过 cleanupStale() 做显式清理,确保页面离开后 params 被正确回收
// 修复前
function extractParams(query: Record<string, string>): ParamObject | undefined {
	const key = query[PARAMS_KEY]
	if (!key) return undefined
	delete query[PARAMS_KEY]
	return paramsManager.get(decodeURIComponent(key)) // get 会做惰性清理,可能误删
}

// 修复后
function extractParams(query: Record<string, string>): ParamObject | undefined {
	const key = query[PARAMS_KEY]
	if (!key) return undefined
	delete query[PARAMS_KEY]
	return paramsManager.peek(decodeURIComponent(key)) // peek 只读取,不清理
}

八、类型导出更新

v1.6.0 新增以下类型导出:

import type { QueryValue, ParamValue, ParamObject } from '@meng-xi/uni-router'

// QueryValue — query 参数输入类型
type QueryValue = string | number | boolean

// ParamValue — params 参数值类型
type ParamValue = string | number | boolean | null | ParamValue[] | { [key: string]: ParamValue }

// ParamObject — params 参数对象类型
interface ParamObject {
	[key: string]: ParamValue
}

升级指南

v1.6.0 完全向后兼容,无需修改现有代码即可升级。以下是推荐的新功能接入方式:

1. 使用 params 替代手动序列化

// 之前:手动 JSON.stringify/parse
uni.setStorageSync('orderData', JSON.stringify(orderData))
await router.push({ path: '/pages/detail/index', query: { id: '001' } })
// 目标页面
const orderData = JSON.parse(uni.getStorageSync('orderData') || '{}')

// 现在:直接使用 params
await router.push({
	path: '/pages/detail/index',
	query: { id: '001' },
	params: { orderData }
})
// 目标页面
const orderData = route.value.params.orderData

2. 使用查询参数增强方法替代手动转换

// 之前
const id = parseInt(route.value.query.id as string) || 0
const enabled = route.value.query.enabled === 'true'

// 现在
const id = route.value.queryInt('id', 0)
const enabled = route.value.queryBool('enabled', false)

3. H5 场景开启 paramsPersistent

如果项目需要 H5 刷新后仍保留 params,可在创建路由器时开启全局默认值:

const router = createRouter({
	routes,
	paramsPersistent: true
})
posted @ 2026-06-23 00:42  PedroQue99  阅读(8)  评论(0)    收藏  举报