Front-end Routing Principles

The core of front-end routing is to change views without making requests to the back end; Instead, load the component corresponding to the route. Vue-router maps components to routes and renders them. Three modes are implemented: Hash mode, History mode and Abstract mode. The default Hash mode. Today’s focus is on Hash mode and History mode.

Hash pattern

  • The principle of

The browser-based hashchange event obtains the hash value of the address through window.location.hash when the address changes. The Router class is constructed and the Routes object is configured to set the hash value and the corresponding component content.

  • advantages
  1. The hash value appears in the URL, but is not included in the Http request, so a hash change does not reload the page
  2. Hash changes trigger the Hashchange event, which controls whether the browser moves forward or backward
  3. Good compatibility
  • disadvantages
  1. It is not beautiful to carry # in the address bar
  2. Only the part after # can be modified, so you can only set the URL of the same document as the current URL
  3. Hash has a volume limit, so only short strings can be added
  4. The new value set must be different from the original to trigger the Hashchange event and add the record to the stack
  5. Each URL change is not an HTTP request, so it is not conducive to SEO optimization
  • Code implementation
<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, Initial scale=1.0" /> <meta HTTP-equiv =" x-UA-compatible "Content =" IE =edge" /> <title>hash</title> </head> <body> <div Class = "main" > < a href = "# / a >" a page < / a > < a href = "#"/b > b page < / a > < a href = "# / c" > c page < / a > < div id = "content" > < / div > < / div > < script > // Router constructor class Router {constructor(routers) {this.routers = {}; Routers. ForEach ((item) => {// Each hash value matches the corresponding component this.route(item.path, () => { document.getElementById("content").innerHTML = item.compontent; }); }); this.init(); } route(path, cb) { this.routers[path] = cb; } init() { window.addEventListener("load", this.updateView.bind(this)); // the browser triggers the hashchange event to call the updateView function window.addeventlistener ("hashchange", this.updateview.bind (this)); } updateView(e) { // console.log("hash window.location", window.location); / / access page hash value through the hash value to update the corresponding component content const hashTag = window. The location. The hash. Slice (1) | | "/". this.routers[hashTag] && this.routers[hashTag](); }} Const routers = [{PATH: "/a", Compontent: '<div> I am a page </div>,}, {path: "/b", Compontent: ` < div > I'm b page < / div > `,}, {path: "/ c", compontent: ` < div > I am c page < / div > `,},]; new Router(routers); </script> </body> </html>Copy the code

The History mode

  • The principle of

Based on HTML5’s new pushState() and replaceState() apis, and the popState event of the browser, when the address changes, the corresponding component is found through window.location.pathname. By constructing Router class, configure routes object to set pathName value and corresponding component content.

  • advantages
  1. No #, more beautiful
  2. The new URL set by pushState() can be any URL of the same origin as the current URL
  3. PushState () sets the new URL to be exactly the same as the current URL, which also adds the record to the stack
  4. PushState () uses the stateObject argument to add any type of data to a record
  5. PushState () sets the title property in addition for later use
  6. A browser forward or backward can trigger the browser’s popState event and get window.Location. pathName to control changes to the page
  • disadvantages
  1. The URL change is an HTTP request, and history.pushState is used to redirect the page without refreshing, so the server is requested again. So the URL of the front end must be the same as the URL of the actual request from the back end. If the URL entered by the user enters enter or the browser refreshes or shares a page path, the URL is inconsistent with the page request URL configured on the back end. In this case, no static resource is matched and a 404 page is returned. Therefore, background configuration support is required to cover candidate resources in all cases. If the URL does not match any static resources, the page or the home page of the app should be returned.
  2. Poor compatibility, specific browser support
  • Code implementation
<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, /> <meta HTTP-equiv =" x-UA-compatible "content=" IE =edge" /> <title>history</title> </head> <body> <div  class="main"> <a href="javascript:;" Path ="/a"> page </a> <a href="javascript:; </a> <a href="javascript:;" Path ="/ C "> page </a> <div ID ="content"></div> </div> <script> Class Router {constructor(routers) {this.routers = {}; routers.forEach((item) => { this.route(item.path, () => { document.getElementById("content").innerHTML = item.compontent; }); }); this.bindClick(); this.init(); } route(path, cb) { this.routers[path] = cb; } bindClick () {/ / the history mode need to manually add the routing through the history of pushState event const links = document. The getElementsByTagName (" a "); // [].forEach.call() => Array.prototype.forEach() [].forEach.call(links, (link) => { link.addEventListener("click", () => { const path = link.getAttribute("path"); this.pushRoute(path); }); }); } pushRoute(path) { window.history.pushState({}, null, path); this.updateView(); } init() { window.addEventListener("load", this.updateView.bind(this)); // The popState event window.addEventListener(" popState ", this.updateView.bind(this)); } updateView(e) { // console.log("history window.location", window.location); // console.log("history window.history", window.history); const currentUrl = window.location.pathname || "/"; this.routers[currentUrl] && this.routers[currentUrl](); }} Const routers = [{PATH: "/a", Compontent: '<div> I am a page </div>,}, {path: "/b", Compontent: ` < div > I'm b page < / div > `,}, {path: "/ c", compontent: ` < div > I am c page < / div > `,},]; new Router(routers); </script> </body> </html>Copy the code

The Abstract model

Supports all javascript runtime modes. Vue-router verifies the environment itself. If the browser API is not available, the route is automatically forced into abstract mode. Abstract mode is also used in mobile native environments.

conclusion

Both hash and history modes are browser features. Vue-router uses these two features to implement front-end routing by invoking interfaces provided by browsers.