Detailed explanation of Vue's hash jump principle

Detailed explanation of Vue's hash jump principle

In new vueRouter, we can pass in a mode attribute, which can receive three values: hash/history/abstract

The difference between hash and history

The history path is more beautiful, such as http://yoursite.com/user/id. History is based on pushState() to complete URL jump without reloading the page. However, forced refresh will still cause problems (the server will solve this problem), so the history mode requires the cooperation of backend personnel.

The hash path will have a #, such as http://yoursite.com#/user/id

HashHistory

class VueRouter{
 constructor(options){
  this.matcher = createMatcher(options.routes || []);
//Here, in order to explain the hash mode, we will not judge which mode the user passed in this.history = new HashHistory(this); //this vue-router instance}
}

The source code creates a base class here. We unify it with the source code. This base class encapsulates the common methods and properties of the three modes. Then we create a HashHistory and a base class History here.

import History from './base'
// hash routing export default class HashHistory extends History{
 constructor(router){
  super(router); //Inherit and call the parent class is equal to call
 }
}
// Base class for routing export default class History {
 constructor(router){
  this.router = router;
 }
}

If it is a hash route, if there is no hash when opening the website, #/ should be added by default

import History from './base';
function ensureSlash(){ 
 if(window.location.hash){
  return 
 }
 window.location.hash = '/'
}
export default class HashHistory extends History{
 constructor(router){
  super(router);
  ensureSlash(); // Ensure there is a hash
 }
}

Let's take a look at the initialization logic (router.init function above)

init(app){
  const history = this.history;
  // When initializing, you should first get the current path and perform matching logic // Let the routing system transition to a certain path const setupHashListener = ()=> {
   history.setupListener(); // Listen for path changes}
  history.transitionTo( // The parent class provides a method responsible for jumping history.getCurrentLocation(), // The subclass obtains the corresponding path // After the jump is successful, register the path listener to prepare for the view update setupHashListener
  )
}

Here we need to implement transitionTo (base class method), getCurrentLocation, setupListener respectively

getCurrentLocation implementation

function getHash(){
 return window.location.hash.slice(1);
}
export default class HashHistory extends History{
 // ...
 getCurrentLocation(){
  return getHash();
 }
}

setupListener Implementation

export default class HashHistory extends History{
 // ...
 setupListener(){
  window.addEventListener('hashchange', ()=> {
   // Transition to the corresponding path according to the current hash value this.transitionTo(getHash());
  })
 }
}

TransitionTo Implementation

export function createRoute(record, location) { // {path:'/',matched:[record,record]}
 let res = [];
 if (record) { // If there is a record while (record) {
   res.unshift(record); // put the parent of the current record in front record = record.parent
  }
 }
 return {
  ...location,
  matched: res
 }
}
export default class History {
 constructor(router) {
  this.router = router;
  // Return the object based on the record and path, which will be used for router-view matching later this.current = createRoute(null, {
   path: '/'
  })
 }
 // Core logic transitionTo(location, onComplete) {
  // To match the path let route = this.router.match(location);
  // The same path does not need to transition if(
   location === route.path && 
   route.matched.length === this.current.matched.length){
   return 
  }
  //Update the route and change the _route attribute on the root instance as mentioned below this.updateRoute(route)
  onComplete && onComplete();
 }
}
export default class VueRouter{
 // ...
 //Make a proxy match(location){
  return this.matcher.match(location);
 }
}

macth method

function match(location){ // Later find the corresponding record based on the path let record = pathMap[location]
 if (record) { // Create the corresponding route according to the record //Parameters: /about/a:{path:xx,component...},path:'/about/a'
  return createRoute(record,{
   path:location
  })
 }
 // If no match is found, return an empty match return createRoute(null, {
  path: location
 })
}

It is not difficult to find that the current property will be changed when the path changes. We can make the current property responsive and refresh the view every time the current changes in the install method.

install(Vue) {
 Vue.mixin({ // Add the beforeCreate method to the life cycle of all components beforeCreate() {
   if (this.$options.router) { 
   //Call the two-way data binding method in the Vue class Vue.util.defineReactive(this,'_route',this._router.history.current);
   } 
  }
 });
 // $route and $router methods are just the most common proxies in Vue. They are just for convenience. Object.defineProperty(Vue.prototype,'$route',{ // Each instance can get the $route property get(){
   return this._routerRoot._route; //Two-way data binding just performed above}
 });
 Object.defineProperty(Vue.prototype,'$router',{ // Each instance can get the router instanceget(){
   return this._routerRoot._router;
  }
 })
 }

The update _route method needs to be called every time the switch route is initialized, because _route is bidirectionally bound to data during installation, and there is no this._router.history.current when it first comes in. Subscription and update operations are performed through the publish-subscribe method; add a listening function in the init method

history.listen((route) => { // Need to update the _route attribute, enter and exit a function app._route = route
});
export default class History {
 constructor(router) {
  // ...
  this.cb = null;
 }
 listen(cb){
  this.cb = cb; //Register function}
 updateRoute(route){
  this.current =route;
  this.cb && this.cb(route); // Update the _route property after updating current}
}

The above is a detailed explanation of the hash jump principle of Vue. For more information about the hash jump principle of Vue, please pay attention to other related articles on 123WORDPRESS.COM!

You may also be interested in:
  • Vue-Element-Admin integrates its own interface to realize login jump
  • Implementing parameter jump function in Vue project
  • How to implement vue page jump
  • Vue implements login, registration, exit, jump and other functions
  • Routing in Vue is not counted in history operations
  • How to redirect PC address to mobile address in Vue

<<:  Solution to MySQL service 1067 error: modify the mysql executable file path

>>:  How to deploy nextcloud network disk using docker

Recommend

Vue3.0 uses the vue-grid-layout plug-in to implement drag layout

Table of contents 1. Plugins 2. Interlude 3. Impl...

Linux uses binary mode to install mysql

This article shares the specific steps of install...

CSS style to center the HTML tag in the browser

CSS style: Copy code The code is as follows: <s...

Front-end state management (Part 1)

Table of contents 1. What is front-end state mana...

Example of automatic stop effect after text scrolling

The effect is very simple, just copy the following...

CSS3 creates web animation to achieve bouncing ball effect

Basic preparation For this implementation, we nee...

Use the sed command to modify the kv configuration file in Linux

sed is a character stream editor under Unix, that...

React handwriting tab switching problem

Parent File import React, { useState } from '...

Common rule priority issues of Nginx location

Table of contents 1. Location / Matching 2. Locat...

JavaScript implementation of the Game of Life

Table of contents Concept Introduction Logical ru...

How to install phabricator using Docker

I am using the Ubuntu 16.04 system here. Installa...

How to correctly modify the ROOT password in MySql8.0 and above versions

Deployment environment: Installation version red ...

MYSQL Left Join optimization (10 seconds to 20 milliseconds)

Table of contents 【Function Background】 [Raw SQL]...