programing

탐색복제 현재 위치("/검색")로 이동할 수 없음

prostudy 2022. 4. 29. 23:12
반응형

탐색복제 현재 위치("/검색")로 이동할 수 없음

여러 번 검색하고 싶을 때는NavigationDuplicated오류. 검색은 탐색 모음에서 수행되며 검색을 구성한 방법은 모델을 사용하여 값을 가져온 다음 해당 값을 ContentSearched 구성 요소에 매개 변수로 전달하고 그 구성 요소에서 검색 값을 수신하는 것이다.

나는 방출기를 사용하는 것이 올바른 방법이라는 것을 알지만, 나는 그것을 사용하는 방법을 아직도 모른다.방출에 접근하는 것은context.emit('', someValue)

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)"}

나바뷰

<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>

콘텐츠 검색됨.부에를 하다

<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>

이런 일이 내게 일어났던 것은 내가 임신했을 때였다.router-link같은 경로를 가리킴./products/1.

사용자는 제품을 클릭할 수 있지만 제품이 이미 클릭(그리고 구성 요소 보기가 이미 로드됨)된 경우 사용자가 다시 클릭하려고 하면 오류/경고가 콘솔에 표시된다.

당신은 Github 문제에 대해 더 배울 수 있다.

부에루터의 주요 공헌자 중 한 명인 포스바는 다음과 같이 제안한다.

router.properties your-path').reason(reason => {}

하지만, 만약 당신이 그것을 원하지 않는다면.catch아무 것도 하지 않는 블록, 문제를 해결하기 위해 라우터 네비게이션과 현재 경로를 비교하고 그것들이 다른 경우에만 탐색할 수 있다.

const path = `/products/${id}`
if (this.$route.path !== path) this.$router.push(path)

참고:$routevue-property가 모든 구성요소에 제공하는 객체.자세한 내용은 경로 개체를 참조하십시오.

이 문제에 대한 최선의 해결책은 우리가 더 이상 사용하지 않는다면 근본적인 수준에서 실행될 수 있다고 생각한다.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);

만약 여러분이 모든 종류의 오류를 잡는 것이 불편하다면, 나는 이 구현이 더 사려 깊다고 생각한다:

this.$router.push("path").catch(error => {
  if (error.name != "NavigationDuplicated") {
    throw error;
  }
});

2021년 현재 글로벌 구성:

난 그저 침묵하고 싶었을 뿐이야.NavigationDuplicated오류, 빈 어획물은 위험할 수 있다.그래서 이렇게 했다.

const router = new VueRouter({/* ... */})

const originalPush = router.push
router.push = function push(location, onResolve, onReject)
{
    if (onResolve || onReject) {
        return originalPush.call(this, location, onResolve, onReject)
    }
 
    return originalPush.call(this, location).catch((err) => {
        if (VueRouter.isNavigationFailure(err)) {
            return err
        }
   
        return Promise.reject(err)
    })
}

부에루터를 초기화할 때 한 번 삽입하십시오.
업데이트해 준 @Oleg Abrazhaev에게 고마워.

나는 검색하다가 같은 문제에 부딪쳤다.내 해결책은 추가하는 것이다.timestamp에게this.$route.query검색 페이지의 매개 변수.

this.$router.push({
    path: "/search",
    query: {
      q: this.searchQuery,
      t: new Date().getTime(),
    }
  });

도움이 되길 바래.

만약 당신이 라우터를 사용하고 있다면.코드를 입력하면 내비게이션이 고장나도 상관 없으며 캐치를 사용하여 코드를 잡아야 한다.

router.push('/location').catch(err => {})

수동:

router.push(location, onComplete?, onAbort?)

당신은 더 간단하게 사용할 수 있다.

router.push("/", () => {});

다음에서 여러 개념을 혼합하셨습니다.router-links 프로그래밍 방식 탐색, 상태 저장소에 매개 변수 쿼리.그것은 당신을 돕고 여기서 "정확한" 해결책이 무엇인지 말하는 것을 약간 어렵게 만든다.

그럼에도 불구하고, 나는 당신에게 가장 좋은 접근방법은 다음과 같은 것이라고 생각한다.
를 (1)로 규정

{
  path: "/search/:searchString",
  component: MySearchComponent,
  props: true
}

2) 대응력을 발휘한다<router-link> 대신router.push

<input type="text" v-model="searchString">
<router-link :to="'/search/'+searchString" tag="button">search</router-link>

3) 접근성searchString검색 구성 요소에서 다음을 통해props: ['searchString']그리고this.searchString

props: ['searchString'],
...
computed: {
  msg() {
    return `Searching for, ${this.searchString}!`;
  }
}

전체 예: https://codesandbox.io/s/vue-routing-example-9zc6g
방금 첫 번째 코드와 상자를 찾았는데router찾을 수 있고, 거기에 맞춰 조정할 수 있어.

TypeScript의 경우 다음과 같이 작동했다.

const superPush = VueRouter.prototype.push

VueRouter.prototype.push = async function push(loc:RawLocation):Promise<Route> {
  try {
    return await superPush.bind(this)(loc)
  } catch (e) {
    if (e?.name === 'NavigationDuplicated') {
      console.warn(e)
      return e
    } else {
      throw e
    }
  }
}

나는 파티에 매우 늦었지만, 나는 이 문제가 목록에 없기 때문에 해결책을 추가해야겠다고 생각했다.나는 중간 검색 페이지를 검색 결과 보기로의 통과로 배치했을 뿐이다.나는 지금 이 페이지를 검색어 사전 처리를 위해 사용하고 있다.

페이지 템플릿:

<template>
  <div>searching ...</div>
</template>  

이 중간 페이지에서 가져오기를 수행하므로 NavigationDuplicated 오류가 사라지고 오류 처리에 대한 책임이 검색 표시줄과 결과 보기에서 모두 분리됨

어디선가 잘 문서화되지 않아 시행착오를 겪었기 때문에 내가 찾은 해결책을 여기에 올린다.누군가에게 유용할 수도 있고, 아니면 누군가가 내가 잘못 해석한 부에로터 경비병을 고쳐줄 수도 있다.

V4를 한다.x와 글로벌을 활용한다.beforeEach보초를 서다

사용 사례는 다음과 같다.

  1. 사용자가 요청하다https://app.com/이미 허가를 받지 않은 경우.
  2. 사용자가 요청하다https://app.com/이것은 인신공격이다.
  3. 사용자는 인증이 필요하거나 필요하지 않은 사용 가능한 라우팅을 요청한다.

경로:

const routes = [
  /**
   * Routes not requiring auth
   */
  {
    path: '/',
    component: () => import('layouts/NotAuthorizedLayout.vue'),
    children: [
      {
        path: 'login',
        name: 'LOGIN',
        component: () => import('pages/Login.vue') 
      },
      {
        path: 'emailsignup',
        component: () => import('pages/EmailSignup.vue') 
      },
      {
        path: 'forgottenpassword',
        component: () => import('pages/ForgottenPassword.vue') 
      }
    ]
  },

  /**
   * Routes requiring auth
   */
  {
    path: '/',
    component: () => import('layouts/AuthorizedLayout.vue'),
    meta: { requiresAuth: true },
    children: [
      { 
        path: 'authors',
        name: 'AUTHORS',
        component: () => import('pages/Authors.vue') 
      },
      { path: 'profile', component: () => import('pages/userProfile/index.vue') }
    ]
  }
];

각 글로벌 가드 이전:

  const redirectToLogin = route => {
    const LOGIN = 'LOGIN';
    if (route.name != LOGIN) {
      return { name: LOGIN, replace: true, query: { redirectFrom: route.fullPath } };
    }
  };

  const redirectToHome = route => {
    const DEFAULT = 'AUTHORS';
    return { name: DEFAULT, replace: true };
  };

  Router.beforeEach((to, from) => {
    const userIsAuthenticated = store.getters['authentication/userIsAuthenticated'];
    const requiresAuth = to.matched.some((route) => route.meta && route.meta.requiresAuth);

    if (!userIsAuthenticated && to.fullPath === '/') {
      return redirectToLogin(to);
    }

    if (!userIsAuthenticated && requiresAuth) {
      return redirectToLogin(to);
    }

    if (to.fullPath === '/') {
      return redirectToHome(to);
    }

    return true;
  });

내 해결책은 확장성의 혼합물이다.prototype수표로Navigation Duplicated Error 다른 오류와 경고가 표시되어야 한다.생산 일주일 후 - 아니오NavigationDuplicated모든 게 잘 되고 있어

import { equals } from 'ramda'

export function register(Vue) {
  const routerPush = Router.prototype.push
  const routerReplace = Router.prototype.push

  const isNavigationDuplicated = (currentRoute, nextRoute) => {
    const { name: nextName, params: nextParams = {}, query: nextQuery = {} } = nextRoute
    const { name, params, query } = currentRoute

    return equals(nextQuery, query) && equals(nextParams, params) && equals(nextName, name)
  }

  Router.prototype.push = function push(location) {
    if (!isNavigationDuplicated(this.currentRoute, location)) {
      return routerPush.call(this, location)
    }
  }

  Router.prototype.replace = function replace(location) {
    if (!isNavigationDuplicated(this.currentRoute, location)) {
      return routerReplace.call(this, location)
    }
  }

  Vue.use(Router)
}

너의 질문은 다소 구식이다.

오류는 "@click.prevent" 입니다.단추가 제출 단추이므로 이벤트가 두 번 호출되므로 이 문장은 작동하지 않는다.

"@제출"을 사용하십시오.예방"이 작동해야 한다(또는 단추 유형을 변경).

url query 파라미터를 같은 값으로 바꾸려고 했을 때 에러가 발생한다는 것을 알았다.

필터가 선택되어 있고 url 쿼리 문자열 매개 변수가 해당 값과 동기화되어 있다.새로운 가치로 바꾸기만 하면 잘 된다.값이 그대로 유지되고(예: 기록에서 되돌아옴) 따라서 쿼리 문자열 파라미터를 동일한 값으로 대체하면 오류가 발생한다.

해결책은 값이 변경되었는지 확인한 후 라우터에서 쿼리 매개 변수를 교체하는 것이었습니다.

let newValue = 'foo'; // new query value for parameter
let qcopy = { ...this.$route.query }; // clone current query
// prevent NavigationDuplicated: Avoided redundant navigation to current location
if (qcopy['your_param'] != newValue){
  qcopy['your_param'] = newValue;
  this.$router.replace({query: qcopy});
}

클릭 전파의 라우터 작업 실행 중지

나는 여기에 다른 사람들에게 유용할 수 있는 높은 수준의 대답을 가지고 있다.그것은 OP에 직접 답하지 않을 수도 있지만, 이러한 생각이 적용된다.

이 문제에 대한 나의 의견은 글로벌 구성을 만지작거리거나 라우터 논리를 파악하려고 하지 않는 것이다.여기저기서 예외로 당신의 앱을 오염시키는 것은 말이 되지 않는다.

필터를 사용한 결과 보기의 경우.필터가 다양한 이유로 라우터 링크로 표시되지만, 실제 라우터 로직은 클릭했을 때 발생하는 것을 원하지 않는다.

따라서, 라우터 동작에 도달하기 전에 클릭을 캡처하십시오!

그럼 두 가지 장점을 모두 누릴 수 있다.

검색 필터(연결로)는...

  1. 뷰 내에서 논리 실행
  2. 여전히 링크로 제시되는 이점(봇 스캔, 사용자 편의성 및 접근성 등) 제공

기술:

사용하다@click.prevent안에 있는 아이에게router-link클릭이 라우터를 누르고 있는 것을 캡처하고 중지하려면.

예:

이전: 라우터 로직 발생(이미 경로에 있음)

<router-link class="nav-link" :to="{name: 'MovieSection'}" >
    <i class="fas fa-film"></i>Peliculas
</router-link>

이후: 라우터 로직 금지, 다른 로직 실행(applyFilter)

<router-link class="nav-link" :to="{name: 'MovieSection'}" >
    <div @click.prevent="myFunc(something)">
        <i class="fas fa-film"></i>Peliculas
    </div>
</router-link>

이 접근 방식을 사용하면 앱에서 복잡하게 높은 수준의 예외를 피할 수 있다.

간단하고 효율적인 솔루션:

if(from.fullPath === to.fullPath){
    return
}

참조URL: https://stackoverflow.com/questions/57837758/navigationduplicated-navigating-to-current-location-search-is-not-allowed

반응형