大家好,
祝你有美好的一天,
我有一个项目,用于将URL与组件上的选择同步。
我将查询对象传递给VueRouter。
VueRouter对该对象进行字符串化并将其用作URL
之后,我可以通过this.$route.query
对象获得该对象(Vuerouter会将该URL解析为普通对象)
这是CodeSandbox上的最低版本
我将这些对象传递给Vue路由器:
{ destinations: ['Hanoi'] }
{ destinations: ['Hanoi','Da Nang'] }
{ destinations: ['Ho Chi Minh City'], travelStyle:['Discovery','Adventure'] }
App.vue
<template>
<div id="app">
<div class="tour">
<h2>Which tour?</h2>
<router-link :to="{ path: 'tours', query: { destinations: ['Hanoi'] } }">Hanoi</router-link>
<br>
<router-link
:to="{ path: 'tours', query: { destinations: ['Hanoi','Da Nang'] } }"
>Hanoi - Da Nang</router-link>
<br>
<router-link
:to="{ path: 'tours', query: { destinations: ['Ho Chi Minh City'] } }"
>Ho Chi Minh City</router-link>
<br>
<br>
<span>Route Query: {{this.$route.query}}</span>
</div>
</div>
</template>
<script>
export default {
name: "App",
};
</script>
问题是,如果我使用VueRouter的默认parseQuery/StringifyQuery
,则URL会很长
tours?destinations=Ho%20Chi%20Minh%20City&travelStyle=Discovery&travelStyle=Adventure
此对象: { destinations: ['Ho Chi Minh City'], travelStyle:['Discovery','Adventure'] }
我按照本主题Custom querystring parser中的说明进行操作,并将qs添加为自定义查询字符串解析器。
使用外部程序包可以让我根据需要控制URL,
此处位于路由器文件中-codesandbox中的完整运行项目
// ...
const router = new VueRouter({
mode: "history",
base: "/",
routes,
stringifyQuery: (query) => {
qs.stringify(query, {
encode: false,
indices: false,
arrayFormat: "comma",
addQueryPrefix: true,
});
},
parseQuery: (query) => {
console.log("queryString", query);
const a = qs.parse(query, {
comma: true,
});
console.log("after parse:", a);
return a;
},
});
现在,在数组中使用逗号时,URL相当短。
tours?destinations=Hanoi
tours?destinations=Hanoi,Da%20Nang
tours?destinations=Ho%20Chi%20Minh%20City&travelStyle=Discovery,Adventure
因为使用逗号分隔数组中的每个元素,所以我们不知道destinations=Hanoi
的意思是{ "destinations": [ "Hanoi" ] }
或{ "destinations": "Hanoi" }
**当我单击指向路由器链接到URL tours?destinations=Hanoi
时,我得到了{ "destinations": [ "Hanoi" ] }
(正确)
但是如果我重新加载该URL,我会得到{ "destinations": "Hanoi" }
(错误)**
他们从that issues开始说,我们可以在数组的键的末尾添加带有单个值的方括号,以获取所需的内容。
des[]=hanoi > { des: [ 'hanoi' ] }
des=hanoi,hai phong > { des: [ 'hanoi', 'hai phong' ] }
这是我在repl.it上的测试文件
const qs = require('qs');
const stringifyQuery = (query) => {
Object.keys(query).forEach((item) => {
if(Array.isArray(query[item])&&query[item].length===1) {
query[item+'[]'] = query[item];
delete query[item];
}
});
return qs.stringify(query, {
encode: false,
indices: false,
arrayFormat: 'comma',
});
};
let parseQuery = (query) =>
qs.parse(query, {
comma: true,
});
const a = {des: ['hanoi']};
const b = {des: ['hanoi','hai phong']};
console.log(stringifyQuery(a)); // des[]=hanoi
console.log(stringifyQuery(b)); // des=hanoi,hai phong
console.log(parseQuery(stringifyQuery(a))); // { des: [ 'hanoi' ] }
console.log(parseQuery(stringifyQuery(b))); // { des: [ 'hanoi', 'hai phong' ] }
一切正常!
但是当我在vue-router上使用它时,就不会了。
再一次,在单击到路由器链接和重新加载相同的URL之间,将显示不同的结果!
对于此URL tours?destinations[]=Hanoi
如果我通过路由器链接单击,它仍然得到{ "destinations[]": [ "Hanoi" ] }
而不是"destinations": [ "Hanoi" ]
但是,如果我重新加载页面,则会得到正确的页面:{ "destinations": [ "Hanoi" ] }
我试图弄清楚发生了什么,但是作为一个新手,这对我来说是很感动的
有人在这个问题上有什么主意或关键词吗?
非常感谢您抽出宝贵的时间阅读我冗长的问题,
对我来说意义重大,我真的很感激!
答案 0 :(得分:0)
我得到了答案,
在我的自定义StringifyQuery中,我对查询对象进行了变异,以在其中添加方括号键(destinations[]: Hanoi)
然后,路由器仍然使用该对象并在下一条路径中显示
这就是为什么当我console.log this.$route.query
显示编辑后的查询(destinations[]: Hanoi)
要解决此问题,我必须避免更改查询对象,仅此而已
CodeSandbox中的完整代码
stringifyQuery: (query) => {
const queryClone = { ...query };
Object.keys(queryClone).forEach((item) => {
if (
Array.isArray(queryClone[item]) &&
queryClone[item].length === 1 &&
!item.includes("[]")
) {
queryClone[`${item}[]`] = queryClone[item];
delete queryClone[item];
}
});
return qs.stringify(queryClone, {
encode: false,
indices: false,
arrayFormat: "comma",
addQueryPrefix: true,
});
},
我的课程:切勿与外部对象混淆,我们必须对其进行克隆(基于上下文的深浅或阴影)并在克隆版本中对其进行编辑