一个例子
Home 页面跳转到 /about 代码如下:
this.$router.push({
path: '/about',
query: {
a: 123,
b: false,
c: null,
d: undefined,
e: [123, 'hello', false],
f: [],
g: {
a: 'hello',
b: 123
},
h: [{ a: 123, b: false, c: [123] }]
}
})
在 /about 页面内执行 console.log(this.$route.query)
@3.2.0 现象
跳转后输出结果如下:
与从 Home 页面跳转时传递的参数一致。
@3.6.5 现象
跳转后输出结果如下:
与跳转时传递的参数相比,有以下几点不同:
- number 类型的值变成了 string 类型
- boolean 类型的值变成了 string 类型
- 数组中的 number 值和 boolean 值也变成了 string 值
- 数组中的 object 值保持了原样
坑
如果 /about 页面中有如下代码,升级后不修改原代码将会掉坑里。
if (query.a === 123)
@3.2.0 版本,结果为 true。
@3.6.5 版本,结果为 false。if (!query.b)
@3.2.0 版本,query.b 为 false, !query.b 为 true。
@3.6.5 版本,query.b 为 'false', !query.b 为 false。
源代码
通过查看 vue-router 项目的 CHANGELOG.md 文档,发现在 @3.4.0 版本时,为了修复 issue 特意将 query 的值做了转换。 vue-router/CHANGELOG.md at dev · vuejs/vue-router (github.com)
该 commit 修改内容如下:
最新的 resolveQuery 函数如下:
export function resolveQuery (
query: ?string,
extraQuery: Dictionary<string> = {},
_parseQuery: ?Function
): Dictionary<string> {
const parse = _parseQuery || parseQuery
let parsedQuery
try {
parsedQuery = parse(query || '')
} catch (e) {
process.env.NODE_ENV !== 'production' && warn(false, e.message)
parsedQuery = {}
}
for (const key in extraQuery) {
const value = extraQuery[key]
parsedQuery[key] = Array.isArray(value)
? value.map(castQueryParamValue)
: castQueryParamValue(value)
}
return parsedQuery
}
const castQueryParamValue = value => (value == null || typeof value === 'object' ? value : String(value))
可以看到 vue-router 对除 value == null || typeof value === 'object' 以外的值都转成了 string。
建议
- 项目中 vue-router 在 @3.4.0 版本以下的,升级到 @3.4.0 以上时要检查下代码中是否有依赖 query 值为 boolean 和 number 的情况。
- query 的值最好只是 string 类型,或者元素为 string 的数组。如需要传递对象,可使用 JSON.stringify() 处理后传递。