Navigation parsing process

  1. Call beforeRouteEnter in the activated component.
  2. Call the global beforeResolve guard (2.5+).
  3. Navigation confirmed.
  4. Call the global afterEach hook.
  5. Trigger a DOM update.
  6. Call the callback passed to Next in the beforeRouteEnter guard, and the created component instance is passed in as an argument to the callback.

The first execution of the runQueue function completes the first six steps of the navguard, after which the third callback passed in is triggered. Const enterGuards = extractEnterGuards(activated) ExtractEnterGuards (activated) will get the beforeRouteEnter in the record in the Activated array. The beforeRouteEnter command is executed after 6. The value of Activated is a newly created component that is likely to be an asynchronous component. The beforeRouteEnter hook defined by that component cannot be obtained unless the component is resolved in step 6. (guard, _, match, key) => {return bindEnterGuard(guard, match, key)}

  • The bindGuard function executes the runQueue function by calling guard.apply(instance, arguments). Instance is the current vuecomponent, That is, when beforeRouteLeave and beforeRouteUpdate are executed,this is referred to the current vuecomponent, so this can be accessed from the two navigational guard hooks.

  • The bindEnterGuard function determines whether a function was passed when next was called. If so, it will execute mate.enteredcbs [key].push(cb). The official description is that this cannot be accessed in the beforeRouteEnter because the jump to the route is not confirmed. When next is executed and the jump is confirmed, the component instance is created and the function passed in next is notified to ask for this. Finally, the incoming CBS is called by calling the handleRouteEntered function, passing in Record.Instances [name] as a parameter (that is, the component instance), The call to handleRouteEntered is a callback to the Data.hook. init component in the RouterView component after the component is initialized.

// src/history/base.js
 runQueue(queue, iterator, () = > {
      // wait until async components are resolved before
      // extracting in-component enter guards
      
      const enterGuards = extractEnterGuards(activated);
      const queue = enterGuards.concat(this.router.resolveHooks);
      runQueue(queue, iterator, () = > {
        if (this.pending ! == route) {return abort(createNavigationCancelledError(current, route))
        }
        this.pending = null;
        onComplete(route);
        if (this.router.app) {
          this.router.app.$nextTick(() = > {
            console.log(444) handleRouteEntered(route); }); }}); }); .function extractEnterGuards (
  activated: Array<RouteRecord>
) :Array<?Function> {
  return extractGuards(
    activated,
    'beforeRouteEnter'.(guard, _, match, key) = > {
      return bindEnterGuard(guard, match, key)
    }
  )
}

function bindEnterGuard (guard: NavigationGuard, match: RouteRecord, key: string) :NavigationGuard {
  return function routeEnterGuard (to, from, next) {
    return guard(to, from.cb= > {
      if (typeof cb === 'function') {
        if(! match.enteredCbs[key]) { match.enteredCbs[key] = [] } match.enteredCbs[key].push(cb) } next(cb) }) } }Copy the code

The beforeRouteEnter in Activated concates with this.router. ResolveHooks to form a new queue. This is the beforeResolve hook for the router instance. Call the global beforeResolve guard (2.5+)

  beforeResolve (fn) {
    return registerHook(this.resolveHooks, fn)
  }
Copy the code

It gets the new queue, it executes the runQueue, and when it’s done it triggers the callback, which triggers onComplete(route), which is the second argument that’s passed in from the initial confirmTransition, and the second argument is a callback, First he executes the updateRoute function and sets this.current to route. This completes a switch to the current path, which is 9. After updateRoute, this.router. AfterHooks are iterated. This is the global afterEach hook that corresponds to 10. Call the global afterEach hook. Updating the DOM will be analyzed in a separate article later. Finally, the callback function passed to Next in the beforeRouteEnter guard is called, and the created component instance is passed as an argument to the callback function. In v3.4.9, the timing of the call has been changed to after the component instance is created in the router-View. Finally, after nextTick, handleRouteEntered is executed again, which is not currently used, probably in case something unexpected happens that causes the hook’s next function to not be executed.

this.confirmTransition(
      route,
      () = > {
        this.updateRoute(route);
        onComplete && onComplete(route);
        this.ensureURL();
        this.router.afterHooks.forEach(hook= > {
          hook && hook(route, prev);
        });

        // fire ready cbs once
        if (!this.ready) {
          this.ready = true;
          this.readyCbs.forEach(cb= >{ cb(route); }); }},err= > {
        if (onAbort) {
          onAbort(err);
        }
        if (err && !this.ready) {
          // Initial redirection should not mark the history as ready yet
          // because it's triggered by the redirection instead
          // https://github.com/vuejs/vue-router/issues/3225
          // https://github.com/vuejs/vue-router/issues/3331
          if(! isNavigationFailure(err, NavigationFailureType.redirected) || prev ! == START) {this.ready = true;
            this.readyErrorCbs.forEach(cb= >{ cb(err); }); }}});Copy the code