vue-roter has several modes

青灯夜游
Release: 2022-07-21 19:02:03
Original
2305 people have browsed it

vue-roter has 3 modes: 1. Hash mode, which uses URL hash value for routing and supports all browsers; the routing implemented in this mode adds ""#" routing name" after the link. . 2. History mode, implemented by the history object provided by h5, relies on H5 History API and server configuration. 3. Abstract mode supports all JS running environments, such as Node server. If it is found that there is no browser API, the route will automatically be forced into this mode.

vue-roter has several modes

The operating environment of this tutorial: windows7 system, vue3 version, DELL G3 computer.

Vue-router is the routing plug-in of the vue framework.

vue-roter has several modes

vue-roter has several modes

According to the vue-router official website, we can clearly see vue- There are three mode values ​​for router

  • hash

  • history

  • abstract

Among them, hash and history are the basis of SPA single-page application.

Let’s talk about the conclusion first: spa application routing has two modes, hash and history, and vue routing has three modes, one more abstract than spa.

Source code analysis

Modify the routing mode through the mode parameter in vue-router:

const router = new VueRouter({
  mode: 'history',
  routes: [...]
})
Copy after login

How to implement it specifically, first we download The source code of vue-router

extracts the processing of mode

class vueRouter {
    constructor(options) {
        let mode = options.mode || 'hash'
        this.fallback =
        mode === 'history' && !supportsPushState && options.fallback !== false
        if (this.fallback) {
            mode = 'hash'
        }
        if (!inBrowser) {
            mode = 'abstract'
        }
        this.mode = mode

        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 after login

You can see that the hash mode is used by default. When set to history, if it is not supported The history method will also force the use of hash mode. When not in a browser environment, such as node, abstract mode is directly forced to use.

hash mode

Before reading this part of the source code, let’s first understand the basics of hash: According to the introduction on MDN, the hash attribute of the Location interface returns a USVString, which will contain the '#' in the URL identifier and the following URL fragment identifier. '#' and the following URL fragment identifier are called hashes. It has the following characteristics:

  • Any characters appearing after the first # will be interpreted by the browser as a position identifier. This means that none of these characters will be sent to the server.

  • If you only change the part after #, the browser will only scroll to the corresponding position and will not reload the web page.

  • Every time you change the # part, a record will be added to the browser's access history. Use the "Back" button to return to the previous position.

  • The hash value can be read through the window.location.hash property, and the window.location.hash property is readable and writable.

  • Use window.addEventListener("hashchange", fun) to monitor hash changes

After understanding these basic knowledge, let’s continue Look at the vue-router source code's processing of /src/history/hash.js

    const handleRoutingEvent = () => {
      const current = this.current
      if (!ensureSlash()) {
        return
      }
      this.transitionTo(getHash(), route => {
        if (supportsScroll) {
          handleScroll(this.router, route, current, true)
        }
        if (!supportsPushState) {
          replaceHash(route.fullPath)
        }
      })
    }
    const eventType = supportsPushState ? 'popstate' : 'hashchange'
    window.addEventListener(
      eventType,
      handleRoutingEvent
    )
    this.listeners.push(() => {
      window.removeEventListener(eventType, handleRoutingEvent)
    })
Copy after login

First also use window.addEventListener("hashchange", fun) to monitor routing changes, and then use the transitionTo method to update the view

  push (location: RawLocation, onComplete?: Function, onAbort?: Function) {
    const { current: fromRoute } = this
    this.transitionTo(
      location,
      route => {
        pushHash(route.fullPath)
        handleScroll(this.router, route, fromRoute, false)
        onComplete && onComplete(route)
      },
      onAbort
    )
  }

  replace (location: RawLocation, onComplete?: Function, onAbort?: Function) {
    const { current: fromRoute } = this
    this.transitionTo(
      location,
      route => {
        replaceHash(route.fullPath)
        handleScroll(this.router, route, fromRoute, false)
        onComplete && onComplete(route)
      },
      onAbort
    )
  }
Copy after login

vue-router's two main API push and replace also simply handle the hash, and then call the transitionTo method to update the view

history mode

Old rules, let's first understand HTML5History Basic knowledge of: According to the introduction on MDN, the History interface allows the manipulation of the browser's session history that has been accessed in tabs or frames. Use the back(), forward() and go() methods to jump backward and forward in the user's history. HTML5 introduced the history.pushState() and history.replaceState() methods, which can add and modify history entries respectively. A little understanding of history.pushState():

window.onpopstate = function(e) {
   alert(2);
}

let stateObj = {
    foo: "bar",
};

history.pushState(stateObj, "page 2", "bar.html");
Copy after login

This will cause the browser address bar to appear as mozilla.org/bar.html, but will not cause the browser to load bar.html , doesn't even check if bar.html exists. That is to say, although the browser URL changes, it will not immediately resend the request to the server. This is also the basis for the spa application to update the view but not rerequest the page. Then we continue to look at the vue-router source code's processing of /src/history/html5.js:

    const handleRoutingEvent = () => {
      const current = this.current

      // Avoiding first `popstate` event dispatched in some browsers but first
      // history route not updated since async guard at the same time.
      const location = getLocation(this.base)
      if (this.current === START && location === this._startLocation) {
        return
      }

      this.transitionTo(location, route => {
        if (supportsScroll) {
          handleScroll(router, route, current, true)
        }
      })
    }
    window.addEventListener('popstate', handleRoutingEvent)
    this.listeners.push(() => {
      window.removeEventListener('popstate', handleRoutingEvent)
    })
Copy after login

The processing logic is similar to hash, use window.addEventListener("popstate", fun) to monitor routing changes, and then Use the transitionTo method to update the view. Methods such as push and replace will not be introduced in detail.

abstract mode

Finally, let’s look directly at the processing of /src/history/abstract.js:

  constructor (router: Router, base: ?string) {
    super(router, base)
    this.stack = []
    this.index = -1
  }
Copy after login

First define 2 variables, stack to record the call The record, index records the current pointer position

  push (location: RawLocation, onComplete?: Function, onAbort?: Function) {
    this.transitionTo(
      location,
      route => {
        this.stack = this.stack.slice(0, this.index + 1).concat(route)
        this.index++
        onComplete && onComplete(route)
      },
      onAbort
    )
  }

  replace (location: RawLocation, onComplete?: Function, onAbort?: Function) {
    this.transitionTo(
      location,
      route => {
        this.stack = this.stack.slice(0, this.index).concat(route)
        onComplete && onComplete(route)
      },
      onAbort
    )
  }
Copy after login

push and replac methods also use stack and index variables to simulate the browser's historical call records.

Summary

Finally we have reached the final summary stage:

  • hash is used in the same way as history. The route in hash contains #, but it is simple to use and does not require the cooperation of the server. From a technical point of view, this is the simplest mode to configure. I feel like this This is also the reason why hash is set as the default mode

  • history mode requires the server to cooperate in handling 404 situations, but there is no # in the route, which is more beautiful than hash.

  • abstract mode supports all JavaScript running environments, such as Node.js server side. If it is found that there is no browser API, the routing will automatically force into this mode.

    Abstract mode does not use the browser API and can be placed in a node environment or desktop application. It is an extension and capability expansion of spa applications.

【Recommended related video tutorials: vue video tutorial, Web front-end entry

The above is the detailed content of vue-roter has several modes. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!