javascript - 通过 router-link 访问链接并通过相同的 URL 重新加载它有什么区别?- Vue - Vue 路由器应用程序
问题描述
大家好,
祝你今天过得愉快,
我有一个项目将 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'] }
应用程序.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>
问题是,如果我使用默认parseQuery/StringifyQuery
的 VueRouter,那么 URL 会很长
tours?destinations=Ho%20Chi%20Minh%20City&travelStyle=Discovery&travelStyle=Adventure
对于这个对象: { destinations: ['Ho Chi Minh City'], travelStyle:['Discovery','Adventure'] }
我按照本主题自定义查询字符串解析器中的说明添加qs作为自定义查询字符串解析器。
并且使用外部包允许我根据需要控制 URL,
这是路由器文件内部 - 在代码沙箱中完整运行的项目
// ...
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
但是出现了另一个问题:Stringify with comma
format 应该将方括号添加到参数名称到具有单个值的标识数组
因为使用逗号来分隔数组内的每个元素,所以我们无法知道是什么destinations=Hanoi
意思{ "destinations": [ "Hanoi" ] }
或{ "destinations": "Hanoi" }
tours?destinations=Hanoi
**当我点击路由器链接到我得到的 URL { "destinations": [ "Hanoi" ] }
(正确)
但是如果我重新加载那个我得到的 URL { "destinations": "Hanoi" }
(错误)**
从那个问题开始,他们说我们可以在一个数组的键末尾添加括号,以获得我们想要的结果。
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 之间显示不同的结果!
对于这个网址tours?destinations[]=Hanoi
如果我点击路由器链接,它仍然会 { "destinations[]": [ "Hanoi" ] }
得到"destinations": [ "Hanoi" ]
但如果我重新加载页面,我得到了正确的页面:{ "destinations": [ "Hanoi" ] }
我试图弄清楚发生了什么,但这对我这个新手来说很感人,
有人对这个问题有任何想法或关键字吗?
非常感谢您抽出宝贵的时间阅读我的长问题,
这对我来说意义重大,我真的很感激!
解决方案
我得到了答案,
在我的自定义 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,
});
},
我的教训:永远不要弄乱外部对象,我们必须克隆它(基于上下文的深度或阴影)并在克隆版本中对其进行编辑
推荐阅读
- bash - 在 bash 中确定 rdf mime 类型
- angular - 在angular2 +中动态添加/删除后无法重新调用按钮
- spring - 使用spring缓存时如何获取cacheKey?
- macos - 在第一次鼠标/触控板单击视图之前,不会在 NSScrollView 子类中调用 touchesBegan
- scheme - 关于 Scheme 上的“with-input-from-file”命令
- c++ - 查找和替换字符串中的单词
- ios - iOS 上的 Metal:何时读取 visibilityResultBuffer?
- python - 对象没有属性“保存”
- c# - 使用正则表达式替换多个标题名称
- java - 如何从一个由多个动词和介词组成的复杂句子中获得主语、动词和宾语?