इतिहास को जोड़े बिना वी-राउटर को कैसे धक्का दिया जाए?


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"})
रोलैंड स्टार्क

@ रोलैंडस्टार्क धन्यवाद - यह बैक बटन का काम करता है और मुख्य मेनू पर वापस जाता है, लेकिन मैं फॉरवर्ड बटन खो देता हूं और फिर से आगे नहीं जा सकता - कोई विचार?
क्लिक करें

प्रक्रिया है: मुख्य मेनू, लोड हो रहा है, परिणाम। मैं $router.replaceलोडिंग से कॉल कर रहा हूं । यह अब मुझे परिणामों से वापस जाने देता है -> मुख्य लेकिन फिर मैं परिणामों के लिए आगे जाने में असमर्थ हूं।
अपवोट

एक अन्य विकल्प होगा कि आपके पास लोडिंग मार्ग न हो। बल्कि परिणाम मार्ग पर सीधे धकेलें, जो डेटा को बनाने पर लाती है, और तब तक एक लोडिंग दृश्य प्रस्तुत करता है जब तक कि यह पूरा न हो जाए। फिर कोई राउटरिंग नहीं है और इतिहास और उपयोगकर्ता प्रवाह $ राऊटर के बिना बरकरार रहना चाहिए।
ArrayKnight

@ClickUpvote आप इस मुद्दे के लिए किसी भी समाधान मिला ...
chans

जवाबों:


8

इस स्थिति को संभालने का एक सही तरीका है

आप घटक घटक का उपयोग कर सकते हैं ग्रेन्युल स्तर में मार्ग को नियंत्रित करने के का

अपने कोड में निम्नलिखित बदलाव करें

मुख्य स्क्रीन घटक में

घटक विकल्पों में इस beofreRouteLeave गार्ड को जोड़ें, 'परिणाम स्क्रीन' पर जाने से पहले आप केवल लोडिंग स्क्रीन पर जाने के लिए मार्ग सेट कर रहे हैं

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

लोडिंग स्क्रीन घटक में

यदि मार्ग फिर से लोडिंग के लिए वापस जाता है, तो उसे यहां नहीं उतरना चाहिए और सीधे मुख्य स्क्रीन पर कूदना चाहिए

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

लोडिंग स्क्रीन में, TheRouteEnter गार्ड की इस तक पहुंच नहीं है, क्योंकि नेविगेशन की पुष्टि होने से पहले गार्ड को कॉल किया जाता है, इस प्रकार नया प्रवेश घटक अभी तक नहीं बनाया गया है। तो इसका फायदा उठाते हुए, आपको परिणाम स्क्रीन से रूट करते समय निकाल दी गई अनंत कॉल नहीं मिलेंगी

परिणाम स्क्रीन घटक में

यदि आप वापस जाते हैं तो यह लोडिंग में नहीं जाना चाहिए और सीधे मुख्य स्क्रीन पर कूदना चाहिए

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

मैंने अभी उसी मुद्दे को पुन: पेश करने के लिए छोटे vue एप्लिकेशन बनाए हैं। यह आपके प्रश्न के अनुसार मेरे स्थानीय में काम करता है। आशा है कि यह आपके मुद्दे को भी हल करेगा


2
यह समाधान भंगुर है (रखरखाव तकनीक ऋण का परिचय) और हर संभव मार्ग के लिए प्रविष्टियों की आवश्यकता होती है जिनके लिए आपको इस कार्यक्षमता की आवश्यकता हो सकती है।
ArrayKnight

पूरी तरह से सहमत हूं, मुझे यह समाधान बिल्कुल पसंद नहीं है
omarjebari

2

मुझे लगता router.replaceहै कि जाने का रास्ता है - लेकिन अभी भी विचार की कुछ पंक्तियाँ (अप्रकाशित):


मूल रूप से $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 थिंकिंग एब्सट्रैक्ट एक बस राउटर-व्यू कंपोनेंट को अपने कोरसिंग रूट कंपोनेंट के साथ एक्सचेंज कर सकती है और किसी तरह के लोडर रैपर को पा सकती है - लेकिन मैं मानती हूं कि
राउटर

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यह सच है, या यदि resultsअशक्त है, हालाँकि आप पसंद करते हैं, तो आप एक नकली डेटासेट बना सकते हैं, अगर आप चाहें तो कंकाल संस्करण बना सकते हैं। अन्यथा, आप चीजों को सिर्फ उसी तरह रख सकते हैं जैसे आपके पास है।


मेरे पास जो लोडिंग स्क्रीन है वह पूरी स्क्रीन को उठा लेती है, इसलिए मैं इसे अपने रूट किए बिना प्रदर्शित करने का तरीका नहीं सोच सकता। लाइव डेमो के लिए naminator.io देखें । ऐसा करने के लिए किसी भी अन्य विचारों के लिए खोलें।
क्लिक करें

मैं इसे सुबह में एक उचित रूप दे दूंगा, लेकिन मेरा प्रारंभिक विचार यह है कि ऐसा कोई कारण नहीं है कि आप स्क्रीन पर लेने के लिए तय की गई स्थिति का उपयोग नहीं कर सकते।
ArrayKnight

अपने डिजाइन को देखते हुए, ऐसा लगता है कि वहाँ कुछ विकल्प हैं: आप परिणाम सामग्री के स्थान पर लोडर को प्रस्तुत कर सकते हैं और फिर डेटा प्राप्त होने के बाद स्विच कर सकते हैं; या आप अपने परिणामों के कंकाल के लोडर को ओवरले कर सकते हैं और फिर परिणामों को अपडेट और पॉप्युलेट कर सकते हैं और लोडर को हटा सकते हैं। यह देखते हुए कि लोडर हेडर (साइट शेल) को कवर नहीं करता है, आपको निश्चित स्थिति की आवश्यकता नहीं होनी चाहिए।
ArrayKnight

@ClickUpvote मुझे बताएं कि आप इस दृष्टिकोण के बारे में कैसा महसूस करते हैं।
ArrayKnight

@ ArrayKnight, सवाल यह है कि मार्ग पहले से ही लागू हैं और उम्मीद के मुताबिक काम कर रहे हैं, यह लोडिंग दृष्टिकोण यहां फिट नहीं हो सकता है, मैं इस स्थिति से गुजर रहा हूं। लोडिंग रूट में एक फॉर्म पोस्ट अनुरोध भी हो सकता है जैसे भुगतान गेटवे या कुछ फॉर्म पोस्ट एक्शन। इस परिदृश्य में हम एक मार्ग को हटाने पर शामिल नहीं कर सकते। लेकिन अभी भी vue राऊटर स्तर में हम प्रवेश करने से पहले हो सकते हैं, क्यों मैंने सुझाव दिया कि यह दृष्टिकोण है, लोडिंग घटक का vue उदाहरण अभी तक इस हुक पर नहीं बनाया गया है और इसका लाभ यह तय करने के लिए है कि इस मार्ग में प्रवेश करना है या पिछले मार्ग पर आधारित नहीं है
chans

1

एक अन्य विकल्प इतिहास एपीआई का उपयोग करना है

एक बार जब आप परिणाम स्क्रीन में होते हैं, तो आप ब्राउज़र के इतिहास में यूआरएल को बदलने के लिए रिप्लेसमेंटस्ट का उपयोग कर सकते हैं ।


0

यह beforeEachराउटर के हुक के साथ किया जा सकता है ।

loadingजब आपको डेटा लोड किया जाता है ( resultsघटक को रीडायरेक्ट करने से पहले ) घटक में आपको विश्व स्तर पर या स्थानीयस्टोरेज में एक चर को बचाने की आवश्यकता होती है :

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

और फिर आपको पहले चर में इस चर की जांच करनी चाहिए और सही घटक पर छोड़ देना चाहिए:

// 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कि क्वेरी बटन पर क्लिक करने पर ( loadingघटक को रूट करने से पहले ) अपने घटक में झूठे मूल्य को रीसेट करने के लिए याद रखें :

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

यह समाधान भंगुर है (रखरखाव तकनीक ऋण का परिचय) और हर संभव मार्ग के लिए प्रविष्टियों की आवश्यकता होती है जिनके लिए आपको इस कार्यक्षमता की आवश्यकता हो सकती है।
ArrayKnight

0

आपकी लोडिंग स्क्रीन को वाउ-राउटर द्वारा बिल्कुल भी नियंत्रित नहीं किया जाना चाहिए। सबसे अच्छा विकल्प जावास्क्रिप्ट द्वारा नियंत्रित अपनी लोडिंग स्क्रीन के लिए एक मोडल / ओवरले का उपयोग करना है। आसपास बहुत सारे उदाहरण हैं। यदि आपको कुछ भी नहीं मिल रहा है तो vue-bootstrap को लागू करने के लिए कुछ आसान उदाहरण हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.