I have the following sequence happening:
Main screen
Loading screen
Results screen
On homepage, when someone clicks a button, I send them to the loading screen, thru:
this.$router.push({path: "/loading"});
And once their task finishes, they are sent to the results screen via
this.$router.push({path: "/results/xxxx"});
The problem is, usually they want to go from results back to the main screen, but when they click back, they're sent to loading again which sends them back to results, so they're stuck in an infinite loop & unable to go back to main screen.
Any ideas how to fix this? I'd ideally like if there was an option like:
this.$router.push({path: "/loading", addToHistory: false});
which would send them to the route without adding it to history.
There is a perfect way to handle this situation
You can use in-component guard to control the route in granule level
Make the following changes in your code
In main screen component
Add this beofreRouteLeave guard in component options, before leaving to 'result screen' you are setting the route to go only through loading screen
beforeRouteLeave(to, from, next) {
if (to.path == "/result") {
next('/loading')
}
next();
},
In loading screen component
If the route go backs from result to loading then , it should not land here and directly jump to main screen
beforeRouteEnter(to, from, next) {
if (from.path == "/result") {
next('/main')
}
next();
},
In loading screen, The beforeRouteEnter guard does NOT have access to this, because the guard is called before the navigation is confirmed, thus the new entering component has not even been created yet. So taking the advantage of this, you won't get the infinite calls fired when routing from results screen
In result screen component
if you use go back then it should not land in loading and directly jump to main screen
beforeRouteLeave(to, from, next) {
if (to.path == "/loading") {
next('/')
}
next();
},
I have just created small vue application to reproduce the same issue. It works in my local as per your question. Hope it resolves your issue as well.
This should have a real answer using this.$router.replace
:
// On login page
// Use 'push' to go to the loading page.
// This will add the login page to the history stack.
this.$router.push({path: "/loading"});
// Wait for tasks to finish
// Use 'replace' to go to the results page.
// This will not add '/loading' to the history stack.
this.$router.replace({path: "/results/xxxx"});
For further reading the Vue Router is using History.pushState() and History.replaceState() behind the scenes.
I guess router.replace
is the way to go - but still some lines of thought (untested):
Basically on $router
change it renders the loading-component until it emits load:stop
, then it renders the 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 {}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With