This is the 23rd day of my participation in the August More Text Challenge.More challenges in August


One, foreword

In the previous chapter, the implementation of route matching was introduced, including the following points:

  • Analysis of routing matching;
  • Router match, matcher. Match, createRoute;

This article continues with route changes that trigger view updates;


Second, the realization of view update

1. Review

Match (location) {this.router.match(location) {this.router.match(location)}

CreateRoute method that creates a matching rule based on the path:

this.current = createRoute(null, {
  path: '/'
});
Copy the code

2. Update the matching result of the current route

So, every time the path changes, the matching rule needs to be updated:

  transitionTo(location, onComplete) {
    // Route matching according to the path; Route: indicates the current matching result
    let route = this.router.match(location);
    this.current = route; // The current property is changed each time the route is switched
    onComplete && onComplete();
  }
Copy the code

3. Check reruns before routing updates

However, the update operation may not be performed every time the path changes, but the check operation must be performed. The second/can match the result;)

  transitionTo(location, onComplete) {
    // Route matching according to the path; Route: indicates the current matching result
    let route = this.router.match(location);
    
    // Duplicate check: If the two paths are the same and the route matching results are the same, no operation is required
    if (location == this.current.path && route.matched.length == this.current.matched.length) { // Prevent duplicate jumps
      return
    }
    
    this.current = route; // The current property is changed each time the route is switched
    onComplete && onComplete();
  }
Copy the code

At this point, when the route changes, the current property is updated, but it does not cause the view to be re-rendered;

4. Responsive implementation of routing

Therefore, we need to make the current property in history responsive data, do dependency collection in the template, and update the view as the data changes:

// install.js

  Vue.mixin({
    beforeCreate() {
      if (this.$options.router) {/ / the root component
        this._routerRoot = this; 
        this._router = this.$options.router;
        this._router.init(this);

        // Target: make this._router.history.current responsive;
        // Function: when current is used for rendering, dependency collection can be performed. When current is updated, view update can be triggered.
        // Define response_route on the root component instance and delegate the attributes of this._router.history.current to _route;
        // Advantage: Reactive updates are triggered when any property in the current object changes;
        // vue.util.definereactive: utility method provided in the Vue constructor to defineReactive data
        Vue.util.defineReactive(this.'_route'.this._router.history.current);
      } else { / / child component
        this._routerRoot = this.$parent && this.$parent._routerRoot; }}});Copy the code

When working with the root component, define reactive data _route:

  • Target: make this._router.history.current responsive;
  • Function: When current is used for rendering, it will collect dependencies. When current is updated, it will trigger view update.
  • Solution: Define the responsive data _route on the root component instance, and proxy the attributes of this._router.history.current to _route in turn;
  • Advantages: Reactive updates are triggered when any property in the current object changes;

When the path changes, the current attribute is updated to the current matched route in the transitionTo method:

  transitionTo(location, onComplete) {
    let route = this.router.match(location);
    // Update the current attribute to the current matched route
    this.current = route;
    onComplete && onComplete();
  }
Copy the code

Update current, but _router does not change, so it cannot trigger reactive update, need to trigger _router update again:

// index.js#VueRouter

init(app) {
    const history = this.history;
    const setUpListener = () = > {
        history.setupListener();
    }
    history.transitionTo(
        history.getCurrentLocation(),
        setUpListener
    )
    // This method is called every time the path changes
    // Triggers an update of the responsive _route data on the root app
    history.listen((route) = >{
        app._route = route; 
    });
}
Copy the code

Add the listen method to the public route handler history/base.js to store the update callback function when the route changes:

// history/base.js

/ / will be
  listen(cb) {
    // Store the update callback for route changes, i.e. App._route = route;
    this.cb = cb;
  }
Copy the code

The _route update callback is triggered in the transitionTo method when the route changes:

// history/base.js

transitionTo(location, onComplete) {
    let route = this.router.match(location);
    if (location == this.current.path && route.matched.length == this.current.matched.length) { // Prevent duplicate jumps
      return
    }
    // Update current with the current route and perform other callbacks
    this.updateRoute(route);
    onComplete && onComplete();
  }
  listen(cb) {
    // Store the update callback for route changes, i.e. App._route = route;
    this.cb = cb;
  }
  /** * Update current; * 2, trigger a responsive update of _route; *@param {*} Route Result of the current matched route */
  updateRoute(route) {
    // The current property is changed each time the route is switched
    this.current = route; 
    // Invoke the saved update callback to trigger a responsive update of app._route
    this.cb && this.cb(route);
  }
Copy the code

When app._route changes, responsive data updates will be triggered, leading to page updates;


Third, the realization of view update

This article introduces the implementation of view update when routing changes, mainly involving the following contents:

  • Update the matching result of the current route.
  • Reregulation before routing update;
  • Responsive implementation of routing;

$route, $router, and