“This is the third day of my participation in the First Challenge 2022, for more details: First Challenge 2022”.

background

A few days ago, the interviewer asked me if I could talk about the two modes of vue-router: #/path and /path. The interviewer smiled a little, hehe, talked a little surface, the deep place did not say, good guy, VUe-Router is ambushed my hand, so this article will take you to vue-Router these two modes of pants out to have a look

What’s the use of #?

What impressed me most was the Hash mode of vue-router. When switching, the root directory is followed by a # character, so why did I select it?

First, let’s talk about the meaning of #

  1. On behalf of the position

# can be used as an anchor to mark the location of an element, and a element can be used as a jump

<a href="#xxx">Jump to XXX position</a>
<! -... Suppose there are many elements in the middle.... -->
<div id="xxx"></div>
Copy the code

Does that fit well with routing or navigation when we click on a page?

  1. Browser URL ‘not recognized’ #

# not the child of the browser URL

  1. When sending an HTTP request, # and the character following it are not recognized, are not included in the request parameters, are not considered the request URL, and are not sent to the server
  2. In the URL field of the current page in the browser, click#+ any character and press Enter will not trigger a page reload, because the browser will assume that you want to jump to somewhere on the current page
  3. The Google Spider ignores the content after the #, meaning that content sites are routed to pages that are not picked up and recommended for search by Google’s browsing engine. Is that why vue-Router 4 says that Hash mode is bad for SEO

So what does # do in vue-Router?

The browser also provides an onHashchange event, which allows you to listen for changes in the route and link them to the browser’s forward and backward actions

So vue-Router’s hash # character is not a myth, but a native API provided by the browser

The difference between hash and History modes

Since it is a detailed solution, it is sure to scratch the source code to see, vue-Router choose different mode is how to deal with it? (Compared with vue-Router 3 and 4)

The first is the vue – router3

export default class VueRouter {...constructor (options: RouterOptions = {}) {...switch (mode) {
      case 'history':
        this.history = new HTML5History(this, options.base)
        break
      case 'hash':
        this.history = new HashHistory(this, options.base, this.fallback)
        break
      case 'abstract':
        this.history = new AbstractHistory(this, options.base)
        break
      default:
        if(process.env.NODE_ENV ! = ='production') {
          assert(false.`invalid mode: ${mode}`)}}}... }Copy the code

As you can see, the history and Hash modes are associated with HTML5History and HashHistory, HTML5History uses the pushState and replaceState methods provided by History. HashHistory uses the Hashchange event listener. Can you guess how vue-Router4 implements the hash mode

// I'm a history mode shell
import { createWebHistory } from './html5'.export function createWebHashHistory(base? : string) :RouterHistory {...return createWebHistory(base)
}
Copy the code

Since Vue-Router4 is directly open to hash mode, we’ll only take a peek at the source code for Vue-Router3

Both hash and history modes need to implement routing functions, namely, the following two cores

  1. Changing the URL does not cause a refresh
  2. Detects URL changes in the following ways
    1. Browser Forward and Back
    2. A The hyperlink of the label changed
    3. Window. The location change

Changing the URL does not cause a refresh

hash

For the first one, the hash mode takes the form of # + path, changing the URL but the browser doesn’t reload it

At the code level, this is a change to window.location.hash

// vue-router/src/history/hash.js 139
function pushHash(path) {
  if (supportsPushState) {
    pushState(getUrl(path));
  } else {
    window.location.hash = path; }}Copy the code

history

Calling the pushState and replaceState methods in History also does not cause a page refresh

history.pushState(state, title[, url])

For details on the parameters, please refer to the MDN documentation

// Jump to the login page
history.pushState(null.""."login");
Copy the code

Detect URL changes

hash

Hash to monitor the hashchange events in vue – the router/SRC/history/hash. 49 lines of js setupListeners method, set up a listener

export class HashHistory extends History {... setupListeners () {const eventType = supportsPushState ? 'popstate' : 'hashchange'
    window.addEventListener( eventType, handleRoutingEvent ) ... }}Copy the code

history

Needless to say, you should know the popState event in the source code above

So in a policy to detect CHANGES in urls, hash is listening for a Hashchange event, and history is listening for a popState event

A method to change the URL

window.location

Hash modiates window.location.hash to modify the URL, whereas history does not

A label





(by default), in hash mode, you can click on the link directly, because there is a # anchor mark, but history should prevent the link, otherwise it will send a request to the server. Call pushState/replaceState

Browser Forward and Back

Go,back, and forward calls are both valid because both hash and history are added to the history stack

conclusion

For hash and history, the hash method was used before 2014. History is a new API for HTML5. In the future, history should be used more frequently. You can refer to the hash mode of Vue-Router4 and directly open it to yes

The resources

Vue – the router hash pattern

Router router implementation principle