Deep Dive into Vue Router 4 Component Navigation Guards
This article explains the internal implementation of component‑level navigation guards in Vue Router 4, covering guard categories, the full navigation lifecycle, the execution mechanism, and detailed source‑code analysis with examples of extractComponentsGuards, beforeRouteUpdate, beforeRouteEnter, and beforeRouteLeave.
Vue Router 4 – Component Guard Deep Dive
The article continues the Vue Router 4 source‑code exploration series , focusing on the component‑level navigation guards. It assumes familiarity with the previous parts that introduced global guards, route‑specific guards, and the overall router architecture.
What You Will Gain
Comprehensive understanding of the core source code behind navigation guards.
Knowledge of the design pattern used for guard implementation.
Insight into the execution flow of component‑level guards.
Navigation Guard Classification
Vue Router 4 defines three major categories of navigation guards:
Global guards – attached to the router instance and triggered on every navigation.
Route‑specific guards – defined in the route configuration and triggered when the matched route is entered.
Component guards – declared inside Vue components and triggered during component creation, update, or before unmount.
Complete Navigation Flow
The navigation process starts with the router’s history listener (e.g., router.push , router.replace , router.go ) and proceeds through a series of guard executions:
History listener triggers navigation.
Global beforeEach guard runs.
If the component is being updated, step 2 runs again followed by the component’s beforeRouteUpdate guard.
If the component is being replaced, step 2 runs again followed by the route’s beforeEnter guard.
Component beforeCreate invokes beforeRouteEnter before rendering.
The beforeResolve guard executes.
After navigation is confirmed, the global afterEach hook runs.
DOM updates are performed.
Before a component is destroyed, the beforeRouteLeave guard runs.
Steps 3, 5, and 9 specifically involve component‑level guards.
Execution Mechanism
All guards are processed using two helper functions:
guardToPromiseFn – wraps a guard callback into a Promise for chainable execution.
runGuardQueue – runs the array of promise‑wrapped guards sequentially.
Component Guard vs. Other Guards
Component guards differ because guardToPromiseFn first extracts the guard functions from the component via extractComponentsGuards . This extraction step is omitted for global and route‑specific guards.
extractComponentsGuards
This utility extracts guard functions from a list of matched route records. Its signature is:
export function extractComponentsGuards(
matched: RouteRecordNormalized[],
guardType: GuardType,
to: RouteLocationNormalized,
from: RouteLocationNormalizedLoaded
) { … }The function iterates over each record, validates component types, normalises async components, and builds an array of promise‑wrapped guard functions. Key steps include:
Warning for empty components in development mode.
Conversion of import('./Component.vue') into a lazy‑loaded function.
Handling of components defined with defineAsyncComponent .
Skipping beforeRouteEnter ‑type guards when the component instance is not yet mounted.
Support for class‑style components via the __vccOpts property.
Creation of guard promises using guardToPromiseFn for both synchronous and asynchronous components.
Guard Implementations
beforeRouteUpdate
.then(() => {
// check in components beforeRouteUpdate
guards = extractComponentsGuards(
updatingRecords,
'beforeRouteUpdate',
to,
from
)
for (const record of updatingRecords) {
record.updateGuards.forEach(guard => {
guards.push(guardToPromiseFn(guard, to, from))
})
}
guards.push(canceledNavigationCheck)
return runGuardQueue(guards)
})beforeRouteEnter
.then(() => {
// clear existing enterCallbacks, these are added by extractComponentsGuards
to.matched.forEach(record => (record.enterCallbacks = {}))
guards = extractComponentsGuards(
enteringRecords,
'beforeRouteEnter',
to,
from
)
guards.push(canceledNavigationCheck)
return runGuardQueue(guards)
})beforeRouteLeave
function navigate(
to: RouteLocationNormalized,
from: RouteLocationNormalizedLoaded
): Promise
{
let guards: Lazy
[]
const [leavingRecords, updatingRecords, enteringRecords] =
extractChangingRecords(to, from)
// beforeRouteLeave runs first
guards = extractComponentsGuards(
leavingRecords.reverse(),
'beforeRouteLeave',
to,
from
)
for (const record of leavingRecords) {
record.leaveGuards.forEach(guard => {
guards.push(guardToPromiseFn(guard, to, from))
})
}
const canceledNavigationCheck = checkCanceledNavigationAndReject.bind(
null,
to,
from
)
guards.push(canceledNavigationCheck)
return (
// run beforeRouteLeave guards
runGuardQueue(guards)
// ... further navigation steps
)
}After extracting and executing the component guards, the router proceeds with the remaining navigation logic.
Images
The article includes several diagrams illustrating the guard categories and the full navigation flow. They are referenced via <img> tags with the original URLs.
Overall, the piece provides a systematic, line‑by‑line walkthrough of how Vue Router 4 processes component‑level navigation guards, offering developers deep insight into the framework’s internal design.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.