기록에 추가하지 않고 vue-router로 푸시하는 방법은 무엇입니까?


12

다음과 같은 순서로 진행됩니다.

  • 메인 화면

  • 로딩 화면

  • 결과 화면

홈페이지에서 누군가가 버튼을 클릭하면 다음을 통해 로딩 화면으로 보냅니다.

this.$router.push({path: "/loading"});

작업이 완료되면 다음을 통해 결과 화면으로 전송됩니다.

this.$router.push({path: "/results/xxxx"});

문제는 일반적으로 결과에서 기본 화면으로 돌아가고 싶지만 다시 클릭하면 다시로드로 전송되어 결과로 다시 전송되므로 무한 루프에 빠지고 갈 수 없습니다 메인 화면으로 돌아갑니다.

이 문제를 해결하는 방법에 대한 아이디어가 있습니까? 다음과 같은 옵션이 있다면 이상적으로 싶습니다.

this.$router.push({path: "/loading", addToHistory: false});

역사에 추가하지 않고 경로로 보낼 것입니다.


5
this.$router.replace({path: "/results/xxxx"})
Roland Starke

@RolandStarke Thanks-뒤로 버튼이 작동하고 메인 메뉴로 돌아갑니다.하지만 앞으로 버튼을 잃어 버리고 다시 앞으로 나아갈 수 없습니다-어떤 아이디어?
Upvote

프로세스는 메인 메뉴, 로딩, 결과입니다. 나는 전화 드렸습니다 $router.replace로드에서. 이제 결과-> 메인에서 되돌아 갈 수 있지만 결과로 진행할 수 없습니다.
Upvote

다른 옵션은 로딩 경로가없는 것입니다. 오히려 작성시 데이터 반입을 수행하는 결과 경로로 직접 푸시 한 다음 완료 될 때까지로드보기를 렌더링합니다. 그런 다음 경로 재 지정이 없으며 $ router.replace 없이도 사용자 흐름이 그대로 유지됩니다.
ArrayKnight

@ClickUpvote이 문제에 대한 해결책을
찾았습니까

답변:


8

이 상황을 처리하는 완벽한 방법이 있습니다

부품 내 가드 를 사용하여 과립 수준에서 경로를 제어 할 수 있습니다.

코드를 다음과 같이 변경하십시오.

메인 화면 구성 요소

구성 요소 옵션에이 beofreRouteLeave guard를 추가하십시오.

beforeRouteLeave(to, from, next) {
   if (to.path == "/result") {
      next('/loading')
    }
    next();
  }, 

화면 구성 요소로드 중

경로가 결과에서로드로 되돌아가는 경우 여기에 착륙해서는 안되고 직접 메인 화면으로 이동하면 안됩니다

beforeRouteEnter(to, from, next) {
    if (from.path == "/result") {
      next('/main')
    }
     next();
  },

로딩 화면에서 beforeRouteEnter 가드에는이 액세스 권한이 없습니다. 내비게이션이 확인되기 전에 가드가 호출되어 새 입력 구성 요소가 아직 작성되지 않았기 때문입니다. 따라서이를 활용하면 결과 화면에서 라우팅 할 때 무한 호출이 발생 하지 않습니다.

결과 화면 구성 요소

뒤로 이동을 사용하면 로딩 중에 착륙하지 않고 직접 메인 화면으로 이동해야합니다

beforeRouteLeave(to, from, next) {
    if (to.path == "/loading") {
      next('/')
    }
    next();
  },

동일한 문제를 재현하기 위해 작은 vue 응용 프로그램을 만들었습니다. 귀하의 질문에 따라 현지에서 작동합니다. 희망은 당신의 문제를 해결 뿐만 아니라.


2
이 솔루션은 부서지기 쉬우 며 (유지 보수 기술 부채가 도입 됨)이 기능이 필요할 수있는 모든 가능한 경로에 대한 항목이 필요합니다.
ArrayKnight


2

나는 router.replace갈 길이라고 생각하지만 여전히 몇 가지 생각의 줄 (unested) :


기본적으로 $router변경되면 로딩 구성 요소가 방출 될 때까지 load:stop렌더링 한 다음router-view


import { Vue, Component, Watch, Prop } from "vue-property-decorator";

@Component<RouteLoader>({
    render(h){
        const rv = (this.$slots.default || [])
        .find(
            child => child.componentOptions
            //@ts-ignore 
            && child.componentOptions.Ctor.extendedOptions.name === "RouterView"
        )
        if(rv === undefined) 
            throw new Error("RouterView is missing - add <router-view> to default slot")

        const loader = (this.$slots.default || [])
        .find(
            child => child.componentOptions
            //@ts-ignore 
            && child.componentOptions.Ctor.extendedOptions.name === this.loader
        )
        if(loader === undefined) 
            throw new Error("LoaderView is missing - add <loader-view> to default slot")
        const _vm = this 
        const loaderNode = loader.componentOptions && h(
            loader.componentOptions.Ctor,
            {
                on: {
                    // "load:start": () => this.loading = true,
                    "load:stop": () => _vm.loading = false
                },
                props: loader.componentOptions.propsData,
                //@ts-ignore
                attrs: loader.data.attrs
            }
        )
        return this.loading && loaderNode || rv
    }
})
export default class RouteLoader extends Vue {
    loading: boolean = false
    @Prop({default: "LoaderView"}) readonly loader!: string
    @Watch("$route")
    loads(nRoute: string, oRoute: string){
        this.loading = true
    }
}

@Component<Loader>({
    name: "LoaderView",
    async mounted(){

        await console.log("async call")
        this.$emit("load:stop")
        // this.$destroy()
    }
})
export class Loader extends Vue {}

이것은 내가보고있는 일종의 구현이지만, 경로 감시 래퍼를 만드는 대신 로딩 구성 요소를 페이지 구성 요소에 직접 구현하는 경향이 있습니다. 이유 : 나는 콘텐츠 구성 요소가 반로드 상태로로드되는 스켈레톤 접근법을 사용하여 사용자에게 무엇을 기대할 수 있는지 시각적으로 피드백 한 다음로드 구성 요소를 오버레이 (모든 작업을 차단 해야하는 경우)하거나 인라인 인라인 인 경우 사용자는 데이터가로드되는 동안 UI를 사용할 수 있습니다. 속도에 대한 사용자 인식과 가능한 한 빨리 원하는 작업을 수행 할 수있는 기능을 차단 해제하는 것입니다.
ArrayKnight

@ArrayKnight 단순히 풀어서 경로의 구성 요소와 라우터 뷰 부품을 교환 할 수 추상적 인 하나를 생각하고 로더 래퍼의 어떤 종류를 얻을 수 -하지만 난 나쁜 디자인과 같은 경로 Feel로에 로더를 넣어 동의
Estradiaz

2

로딩 경로에서 무슨 일이 일어나고 있는지에 대해 우리가 아는 것이 거의 없다는 점을 고려하면 힘든 전화입니다.

그러나...

로드 / 라우팅을 구축 할 필요가 없었으며, 초기화 / 데이터 수집 단계에서 여러 경로에서 렌더링되는 구성 요소 만로드했습니다.

로딩 경로가 없다는 한 가지 주장은 사용자가 잠재적으로이 URL로 직접 이동할 수 있다는 것입니다. 그러면 사용자를 어디로 보낼지 또는 어떤 조치를 취할지 알 수있는 컨텍스트가 충분하지 않은 것 같습니다. 이 시점에서 오류 경로로 넘어가는 것을 의미 할 수 있습니다. 전반적으로 좋은 경험은 아닙니다.

또 다른 방법은 경로를 단순화하면 경로 간 탐색이 훨씬 단순 해지고를 사용하지 않고 예상대로 작동하는 것입니다 $router.replace.

나는 이것이 당신이 요구하는 방식으로 질문을 해결하지 못한다는 것을 이해합니다. 그러나이로드 경로를 다시 생각하는 것이 좋습니다.

<shell>
    <router-view></router-view>
</shell>

const routes = [
  { path: '/', component: Main },
  { path: '/results', component: Results }
]

const router = new VueRouter({
  routes,
})

const app = new Vue({
  router
}).$mount('#app')

껍질

<div>
    <header>
        <nav>...</nav>
    </header>
    <main>
        <slot></slot>
    </main>
</div>

메인 페이지

<section>
    <form>...</form>
</section>

{
    methods: {
        onSubmit() {
            // ...

            this.$router.push('/results')
        }
    }
}

결과 페이지

<section>
    <error v-if="error" :error="error" />
    <results v-if="!error" :loading="loading" :results="results" />
    <loading v-if="loading" :percentage="loadingPercentage" />
</section>

{
    components: {
        error: Error,
        results: Results,
    },
    data() {
        return {
            loading: false,
            error: null,
            results: null,
        }
    },
    created () {
        this.fetchData()
    },
    watch: {
        '$route': 'fetchData'
    },
    methods: {
        fetchData () {
            this.error = this.results = null
            this.loading = true

            getResults((err, results) => {
                this.loading = false

                if (err) {
                    this.error = err.toString()
                } else {
                    this.results = results
                }
            })
        }
    }
}

결과 구성 요소

기본적으로 이미 가지고있는 것과 동일한 결과 구성 요소이지만 loading사실이거나 resultsnull 인 경우 원하는 경우 가짜 데이터 세트를 만들어 골격 버전을 반복하고 만들 수 있습니다. 그렇지 않으면, 당신이 가진 그대로 물건을 유지할 수 있습니다.


로딩 화면이 전체 화면을 차지하므로 자체 경로가 없어도 화면을 표시하는 방법을 생각할 수 없습니다. 라이브 데모는 naminator.io 를 참조하십시오 . 이 작업을 수행하기위한 다른 아이디어를여십시오.
Upvote

아침에 적절한 모습을 보여줄 것이지만, 처음에 생각한 것은 화면을 차지하기 위해 고정 된 위치를 사용할 수 없었던 이유가 없다는 것입니다.
ArrayKnight

디자인을 살펴보면 몇 가지 옵션이있는 것 같습니다. 결과 내용 대신 로더를 렌더링 한 다음 데이터를 가져온 후 전환 할 수 있습니다. 또는 결과 골격의 로더를 오버레이 한 다음 결과를 업데이트하고 채우고 로더를 제거 할 수 있습니다. 로더가 헤더 (사이트 쉘)를 덮지 않는다는 점을 고려하면 위치를 고정 할 필요는 없습니다.
ArrayKnight

@ClickUpvote는이 접근법에 대해 어떻게 생각하는지 알려주세요.
ArrayKnight

@ArrayKnight, 문제는 경로가 이미 구현되었으며 예상대로 작동한다는 것입니다. 이로 드 방법이 여기에 맞지 않을 수 있습니다.이 같은 상황을 겪었습니다. 로딩 경로에는 지불 게이트웨이 또는 일부 양식 게시 조치와 같은 양식 게시 요청이있을 수도 있습니다. 이 시나리오에서는 경로 제거를 구성 할 수 없습니다. 그러나 여전히 vue 라우터 수준에서 우리는 enter guards 전에 가질 수 있습니다.이 접근법은 왜로드 구성 요소의 vue 인스턴스 가이 후크에서 아직 생성되지 않았 으며이 경로에 진입할지 여부를 결정하는 이점은 이전 경로를 기반으로합니다
chans

1

또 다른 옵션은 History API 를 사용하는 것 입니다.

결과 화면에 있으면 ReplaceState 를 사용 하여 브라우저 기록에서 URL을 바꿀 수 있습니다 .


0

이것은 beforeEach라우터 의 후크 로 수행 할 수 있습니다 .

loading데이터를로드 할 때 ( results구성 요소로 리디렉션하기 전에) 구성 요소의 전역 또는 localStorage에 변수를 저장해야합니다 .

export default {
  name: "results",
  ...
  importantTask() {
    // do the important work...
    localStorage.setItem('DATA_LOADED', JSON.stringify(true));
    this.$router.push({path: "/results/xxxx"});
  }
}

그런 다음 beforeEach 후크에서이 변수를 확인하고 올바른 구성 요소로 건너 뛰십시오.

// router.js...
router.beforeEach((to, from, next) => {
  const dataLoaded = JSON.parse(localStorage.getItem('DATA_LOADED'));
  if (to.name === "loading" && dataLoaded)
  {
    if (from.name === "results")
    {
      next({ name: "main"} );
    }
    if (from.name === "main")
    {
      next({ name: "results"} );
    }
  }
  next();
});

또한 main구성 요소로 라우팅하기 전에 쿼리 버튼을 클릭 할 때 구성 요소 에서 값을 false로 다시 설정해야합니다 loading.

export default {
  name: "main",
  ...
  queryButtonClicked() {
    localStorage.setItem('DATA_LOADED', JSON.stringify(false));
    this.$router.push({path: "/loading"});
  }
}

이 솔루션은 부서지기 쉬우 며 (유지 보수 기술 부채가 도입 됨)이 기능이 필요할 수있는 모든 가능한 경로에 대한 항목이 필요합니다.
ArrayKnight

0

로딩 화면은 vue-router로 전혀 제어해서는 안됩니다. 가장 좋은 옵션은 자바 스크립트로 제어되는 로딩 화면에 모달 / 오버레이를 사용하는 것입니다. vue에 대한 많은 예제가 있습니다. 아무것도 찾을 수 없다면 vue-bootstrap에는 구현하기 쉬운 예제가 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.