Javascript NavigationDuplicated 导航到当前位置(“/search”)是不允许的 [vuejs]
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/57837758/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
NavigationDuplicated Navigating to current location ("/search") is not allowed [vuejs]
提问by Chris Michael
Problem
问题
Hi dev,
嗨开发者,
I have the problem of when I want to do a search multiple times it shows me the NavigationDuplicatederror. My search is in the navbar and the way I have configured the search is to take the value using a model and then pass the value as a parameter to the ContentSearched component, and then receive the value of the search in that components.
我有一个问题,当我想多次进行搜索时,它会向我显示NavigationDuplicated错误。我的搜索在导航栏中,我配置搜索的方式是使用模型获取值,然后将该值作为参数传递给 ContentSearched 组件,然后在该组件中接收搜索值。
I know the right way is to use a emitter, but I still don't know how to learn to use it. To access the emit is context.emit('', someValue)
我知道正确的方法是使用发射器,但我仍然不知道如何学习使用它。访问发射是context.emit('', someValue)
If someone can help me solve the problem I will appreciate it.
如果有人能帮我解决问题,我将不胜感激。
NavigationDuplicated?{_name: "NavigationDuplicated", name: "NavigationDuplicated", message: "Navigating to current location ("/search") is not allowed", stack: "Error? at new NavigationDuplicated (webpack-int…node_modules/vue/dist/vue.runtime.esm.js:1853:26)"}
NavBar.vue
导航栏.vue
<template>
<nav class="navbar navbar-expand-lg navbar-dark bg-nav" v-bind:class="{'navbarOpen': show }">
<div class="container">
<router-link to="/" class="navbar-brand">
<img src="../assets/logo.png" alt="Horizon Anime" id="logo">
</router-link>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation" v-on:click.prevent="toggleNavbar">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent" v-bind:class="{'show': show }">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<router-link class="nav-link" to="/" ><i class="fas fa-compass"></i> Series</router-link>
</li>
<li class="nav-item">
<router-link class="nav-link" :to="{name: 'EpisodesSection'}" ><i class="fas fa-compact-disc"></i> Episodios</router-link>
</li>
<li class="nav-item">
<router-link class="nav-link" :to="{name: 'MovieSection'}" ><i class="fas fa-film"></i> Peliculas</router-link>
</li>
</ul>
<div class="search-bar">
<form class="form-inline my-2 my-lg-0">
<input class="form-control mr-sm-2" v-model="query" type="search" placeholder="Buscar películas, series ..." aria-label="Search">
<button class="btn btn-main my-2 my-sm-0" @click.prevent="goto()" type="submit"><i class="fas fa-search"></i></button>
</form>
</div>
</div>
</div>
</nav>
</template>
<script>
import {value} from 'vue-function-api';
import {useRouter} from '@u3u/vue-hooks';
export default {
name: "NavBar",
setup(context){
const {router} = useRouter();
const query = value("");
let show = value(true);
const toggleNavbar = () => show.value = !show.value;
const goto = () =>{
let to = {name: 'ContentSearched' , params:{query: query}}
router.push(to);
};
return{
show,
toggleNavbar,
goto,
query
}
}
}
</script>
ContentSearched.vue
内容搜索.vue
<template>
<div class="container">
<BoxLink/>
<main class="Main">
<div class="alert alert-primary" role="alert">
Resultados para "{{query}}"
</div>
<div v-if="isLoading">
<!-- <img class="loading" src="../assets/loading.gif" alt="loading"> -->
</div>
<div v-else>
<ul class="ListEpisodios AX Rows A06 C04 D02">
<li v-for="(content, index) in contentSearched" :key="index">
<div v-if="content.type === 'serie'">
<Series :series="content"/>
</div>
<div v-if="content.type === 'pelicula'">
<Movies :movies="content"/>
</div>
</li>
</ul>
</div>
</main>
</div>
</template>
<script>
import {onCreated} from "vue-function-api"
import {useState , useRouter , useStore} from '@u3u/vue-hooks';
import BoxLink from "../components/BoxLink";
import Movies from "../components/Movies";
import Series from "../components/Series";
export default{
name: 'ContentSearched',
components:{
BoxLink,
Movies,
Series
},
setup(context){
const store = useStore();
const {route} = useRouter();
const state = {
...useState(['contentSearched' , 'isLoading'])
};
const query = route.value.params.query;
onCreated(() =>{
store.value.dispatch('GET_CONTENT_SEARCH' , query.value);
});
return{
...state,
query,
}
}
};
</script>
回答by roli roli
This happened to me when I had a router-linkpointing to the same route. e.g. /products/1.
当我router-link指向同一条路线时,这发生在我身上。例如/products/1。
The user is able to click on the products, but if a product was already clicked (and the component view was already loaded)and the user attempts to click it again, the error/warning shows in the console.
用户可以点击产品,但如果产品已经被点击(并且组件视图已经加载)并且用户尝试再次点击它,错误/警告会显示在控制台中。
You can learn more on the github issue..
您可以在 github 问题上了解更多信息。.
Posva, one of the main contributors of vue-router suggests:
Posva,vue-router 的主要贡献者之一建议:
router.push('your-path').catch(err => {})
router.push('你的路径').catch(err => {})
However, if you don't want to have a catchblock which does nothing, in order to solve the issue you can compare the router navigation with the current route and only navigate if they differ:
但是,如果您不想要一个catch什么都不做的块,为了解决这个问题,您可以将路由器导航与当前路线进行比较,并且仅在它们不同时才进行导航:
const path = `/products/${id}`
if (this.$route.path !== path) this.$router.push(path)
Note: $routeis an object provided by vue-router to every component. See The Route Objectfor more info.
注意:$route是 vue-router 提供给每个组件的对象。有关更多信息,请参阅路由对象。
回答by Abhishek Shastri
I think the best solution to this can be solved at the root label if we are not going to use further Router.pushas asynchronous call.
如果我们不打算进一步Router.push用作异步调用,我认为最好的解决方案可以在根标签处解决。
import Router from 'vue-router';
const originalPush = Router.prototype.push;
Router.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err)
};
Vue.use(Router);
回答by fguillen
If you are not feeling comfortable catching all kind of errors, I think this implementation is more considerate:
如果你对捕捉所有类型的错误感到不舒服,我认为这个实现更体贴:
this.$router.push("path").catch(error => {
if (error.name != "NavigationDuplicated") {
throw error;
}
});
回答by Chan Yoong Hon
if you are using router.push in your code and you don't care about the navigation failing, you should catch it by using catch:
如果您在代码中使用 router.push 并且不关心导航失败,则应该使用 catch 来捕获它:
router.push('/location').catch(err => {})
回答by TommyF
You mixed multiple concepts here from router-links to programmatic navigation, to query params to a state store. That makes it a bit difficult to help you and tell you what the "correct" solution here is.
您在这里混合了多个概念,从router-links 到编程导航,再到查询参数到状态存储。这使得帮助您并告诉您这里的“正确”解决方案是什么有点困难。
Nonetheless, I think the best approach for you would be to:
1) define your route as
尽管如此,我认为对您来说最好的方法是:
1)将您的路线定义为
{
path: "/search/:searchString",
component: MySearchComponent,
props: true
}
2) use a responsive <router-link>instead of your router.push
2)使用响应式<router-link>而不是你的router.push
<input type="text" v-model="searchString">
<router-link :to="'/search/'+searchString" tag="button">search</router-link>
3) access the searchStringin your search component via props: ['searchString']and this.searchString
3)searchString通过props: ['searchString']和访问您的搜索组件中的this.searchString
props: ['searchString'],
...
computed: {
msg() {
return `Searching for, ${this.searchString}!`;
}
}
Full example: https://codesandbox.io/s/vue-routing-example-9zc6g
Note, I just forked the first codesandbox with a routerI could find, adjust accordingly.
完整示例:https:
//codesandbox.io/s/vue-routing-example-9zc6g 注意,我只是用router我能找到的第一个代码沙箱分叉,相应地调整。
回答by Ruslan Semenov
in manual:
在手册中:
router.push(location, onComplete?, onAbort?)
You can use more simply
您可以更简单地使用
router.push("/", () => {});
回答by hero592
Here's is a simple and efficient solution:
这是一个简单有效的解决方案:
if(from.fullPath === to.fullPath){
return
}

