这篇记录我在项目里踩过的坑:从列表页跳详情页时,参数传过去了但展示错乱(看起来像"写死")。
整理一份可复用的跳转带参方案,后续开发直接套。
一、跳转带参的底层逻辑
小程序页面跳转(uni.navigateTo)本质是:
- 在 A 页拼 URL query 参数
- 在 B 页
onLoad(options)接收参数
options里的值默认都是字符串。
二、最基础:传简单参数(id、name)
A 页面:发起跳转
function goDetail() {
const id = 1001
const name = encodeURIComponent('内蒙古能源服务有限公司')
uni.navigateTo({
url: `/pages/detail/detail?id=${id}&name=${name}`
})
}
B 页面:接收参数
import { onLoad } from '@dcloudio/uni-app'
onLoad((options) => {
const id = Number(options?.id || 0) // 字符串转数字
const name = options?.name ? decodeURIComponent(options.name) : ''
console.log('id:', id)
console.log('name:', name)
})
三、进阶:传对象参数(常用)
query 不能直接塞对象,需要先 JSON.stringify,再 URL 编码。
A 页面
function goDetailWithObject(item: any) {
const data = encodeURIComponent(JSON.stringify(item))
uni.navigateTo({
url: `/pages/detail/detail?data=${data}`
})
}
B 页面
onLoad((options) => {
let detailData: any = null
if (options?.data) {
try {
detailData = JSON.parse(decodeURIComponent(options.data))
} catch (error) {
console.warn('data parse failed:', error)
}
}
console.log('detailData:', detailData)
})
四、项目实战推荐:对象 + 关键字段兜底
这是我现在最推荐的模式,抗异常能力强。
为什么要"兜底"
- 有些端上场景对象参数解析可能失败
- 或者 URL 过长导致
data不完整 - 关键展示字段(如分数、等级、公司名)不能丢
A 页面(推荐写法)
const encoded = encodeURIComponent(JSON.stringify(item))
const score = encodeURIComponent(String(item?.creditScore ?? ''))
const level = encodeURIComponent(String(item?.creditLevel ?? ''))
const companyName = encodeURIComponent(String(item?.companyName ?? ''))
uni.navigateTo({
url: `/pages_public/CustomerManagement/detail?id=${item.id}&data=${encoded}&creditScore=${score}&creditLevel=${level}&companyName=${companyName}&userStatus=${userStatus.value}`
})
B 页面(接收 + 合并)
onLoad((options: any) => {
// 可选:统一解码工具
const decodeText = (value: unknown) => {
if (value === null || value === undefined) return ''
const text = String(value)
if (!text) return ''
try {
return decodeURIComponent(text)
} catch {
return text
}
}
let data: Record<string, any> | null = null
if (options?.data) {
try {
data = JSON.parse(decodeURIComponent(options.data))
} catch (error) {
console.warn('options.data parse failed:', error)
}
}
// 关键字段兜底
const scoreText = decodeText(options?.creditScore)
const levelText = decodeText(options?.creditLevel)
const nameText = decodeText(options?.companyName)
const fallbackFromQuery = {
companyName: nameText,
creditLevel: levelText,
creditScore: scoreText !== '' && Number.isFinite(Number(scoreText)) ? Number(scoreText) : undefined
}
// 合并优先级:默认值 < query兜底 < data对象
const finalDetail = {
companyName: '-',
creditLevel: '-',
creditScore: undefined,
...fallbackFromQuery,
...(data || {})
}
console.log(finalDetail)
})
五、常见坑清单(高频)
-
参数名不一致
URL 写
companyName,接收写成options.companyname,直接拿不到。 -
忘记 encode/decode
中文、空格、
&、?容易把 URL 搞坏。 -
把 options 当 number 用
options.id是字符串,记得Number(...)。 -
对象太大导致 URL 过长
不要传超大对象,建议只传关键字段或只传
id。 -
默认值写死引发误判
fallback 默认值别写业务值(如"优秀/87"),应写中性值(
-、undefined)。
六、工程实践建议(最稳)
方案 A(最推荐)
- 只传
id - 详情页根据
id请求接口拿最新数据
**优点:**数据真实、长度安全、可控性强
**缺点:**首次展示依赖接口返回速度
方案 B(体验更好)
- 传
id + 关键展示字段 - 先展示传参,再异步请求刷新
**优点:**秒开、又有最终一致性
**缺点:**代码稍复杂
七、我自己的结论
- Demo 阶段:对象传参效率高
- 线上阶段:
id拉取最稳 - 折中最佳:
id + 关键字段兜底 + try/catch 解析 + 中性默认值
八、可直接复用的"跳转模板"
// A 页面
const payload = encodeURIComponent(JSON.stringify(item))
const companyName = encodeURIComponent(String(item.companyName ?? ''))
const score = encodeURIComponent(String(item.creditScore ?? ''))
const level = encodeURIComponent(String(item.creditLevel ?? ''))
uni.navigateTo({
url: `/pages/detail/detail?id=${item.id}&data=${payload}&companyName=${companyName}&creditScore=${score}&creditLevel=${level}`
})
// B 页面
onLoad((options) => {
let data = null
try {
data = options?.data ? JSON.parse(decodeURIComponent(options.data)) : null
} catch {}
const result = {
companyName: options?.companyName ? decodeURIComponent(options.companyName) : '',
creditScore: options?.creditScore ? Number(decodeURIComponent(options.creditScore)) : undefined,
creditLevel: options?.creditLevel ? decodeURIComponent(options.creditLevel) : '',
...(data || {})
}
// 使用 result
})