必须在 onload 或路由守卫中解析 url 参数,而非使用过滤器;因为过滤器是纯函数,无法访问 this.$route、处理编码异常或触发响应式更新,且不支持 try/catch 容错。

不能直接用过滤器把 URL 参数转为对象 —— 过滤器只适合格式化已有数据,不负责解析 URL。你真正需要的是在 onLoad 或路由守卫里做解析,而不是写个 urlToObj 过滤器塞进模板里。
为什么不能在模板里用过滤器解析 URL 参数
过滤器(Vue.filter)本质是纯函数,只接收一个值、返回一个值,它没有访问 options 或 this.$route.query 的能力。你在模板里写 {{ $route.fullPath | parseUrl }},$route.fullPath 是字符串没错,但你没法在过滤器内部调用 decodeURIComponent + URLSearchParams + JSON.parse 等组合逻辑,更没法处理编码异常、重复键、空值等边界情况。
- 过滤器无法捕获原始 query 字符串中的编码错误(比如未闭合的
%xx) - 过滤器不感知页面生命周期,无法在
onLoad时同步拿到参数并触发响应式更新 - 强行封装成过滤器会导致逻辑分散:解析在 filter 里,使用在 template 里,出错难定位
正确做法:在 onLoad 中解析 options
uni-app 页面跳转时,URL 参数会以 plain object 形式传入 onLoad(options),**这个 options 已经是解码后的字符串对象,不是原始 query 字符串**。你不需要手动 decodeURIComponent,除非你传的是嵌套 JSON 字符串(如 ?item=%7B%22id%22%3A1%7D)。
- 普通参数(
/page?id=123&name=test)→options = { id: '123', name: 'test' },直接用 - JSON 字符串参数(
/page?item=%7B%22id%22%3A1%7D)→options = { item: '{"id":1}' },需手动JSON.parse(options.item) - 如果传参用了
encodeURIComponent(JSON.stringify(obj)),接收端必须配对使用JSON.parse(decodeURIComponent(options.item))
示例:
onLoad(options) {
// 普通参数,直接赋值
this.id = options.id || ''
this.name = options.name || ''
// JSON 字符串参数,需双重解析
if (options.item) {
try {
this.item = JSON.parse(decodeURIComponent(options.item))
} catch (e) {
console.error('parse item failed:', e)
this.item = {}
}
}
}
想复用解析逻辑?封装成工具函数,别塞过滤器
如果你多个页面都要解析类似 item 这种 JSON 字符串参数,应该抽成工具函数,比如放在 utils/url.js:
export function parseQueryItem(str) {
if (!str) return {}
try {
return JSON.parse(decodeURIComponent(str))
} catch {
return {}
}
}
然后在页面中导入使用:
import { parseQueryItem } from '@/utils/url.js'
onLoad(options) {
this.item = parseQueryItem(options.item)
}
- 不依赖 Vue 实例,可单元测试
- 错误处理明确,不会静默失败
- 和过滤器无关,也不污染全局 filter 命名空间
注意:小程序端 URL 长度限制和 H5 差异
小程序对 URL query 长度有硬限制(通常 ≤ 2048 字符),而 H5 没这限制。如果你传大对象,JSON.stringify 后再 encodeURIComponent 很容易超限,导致参数被截断、JSON.parse 报 Unexpected end of JSON input。
- 超长对象优先走 Vuex / Pinia / globalData 缓存,用 ID 代替整段数据传参
- 必须传的话,服务端生成短 token,前端用 token 换数据
- 不要在过滤器里尝试做容错 —— 它连 try/catch 都没地方写
真正要处理 URL 参数的地方永远是 onLoad 或路由守卫,不是模板里的管道符。











