My Vue app shows a loading screen whenever a route is loading because code-split routes sometimes take a few seconds to load. It does this using a global beforeEach hook.
// App component
this.$router.beforeEach(() => { this.loading = true })
this.$router.afterEach(() => { this.loading = false })
this.$router.onError(() => { this.loading = false })
The problem with this is if I create a guard on a route definition (like beforeEnter), calling next(false) won't trigger afterEach or onError, so it leaves the app in a loading state forever.
One thing I tried was to use beforeResolve instead of beforeEach. This didn't work out because my beforeEnter route guards are asynchronous, and I want to show the loading screen while they execute.
Another possible solution is to always call next(error) instead of next(false) so that the onError hook is triggered. But that's a bug waiting to happen later on, when someone tries to use the navigation guard API as intended.
One last option is to isolate the this.loading logic into a globally-accessible class or event bus and make route guards handle it on a case-by-case basis.
But my preference would be to set it and forget it. Is there a global hook that gets called when navigation is cancelled? And why isn't afterEach called in this scenario?