The front-end routing

This is the 25th day of my participation in the August Genwen Challenge.More challenges in August

A route is essentially a mapping table

The mapping between path addresses and components is maintained in this mapping table

Routing development

The back-end routing

In the early days of web development, entire HTML pages were rendered by servers

  • The server directly produces and renders the corresponding HTML pages and returns them to the client for display

  • At this point each page has its own corresponding URL, that is, the URL

  • The URL is sent to the server, which matches the URL with the re, and gives it to a Controller for processing

  • The Controller does all sorts of processing and eventually generates HTML or data and returns it to the former

The above operation, when we need to request different path content in the page, the server to handle, the server render the entire page, and return the page to the client

In this case, these routes maintain the relationship between URLS and pages, so they are called back-end routes

Advantages: In this case, the rendered page does not need to load any separate JS and CSS, can be presented directly to the browser, which is also conducive to SEO optimization

Disadvantages:

  1. Each module of the entire page needs to be written and maintained by the back-end staff
  2. HTML code gets mixed up with data and logic, and writing and maintaining it can be very messy
Front end separation

The front-end rendering

  • With the advent of Ajax, there was a development pattern of front – and back-end separation

  • The static resources involved in each request are retrieved from the static resource server, including HTML+CSS+JS,

    These requested resources are then rendered in the front end

  • Each time a client requests a file, it requests it from the static resource server

  • Unlike the previous back-end routing, the back-end is only responsible for providing the API (only the data)

  • The front end gets the data through Ajax and can render it to the page through JavaScript

Advantages:

  1. Clear accountability at the front and back ends, with the back end focused on data and the front end focused on interaction and visualization
  2. When mobile (iOS/Android) comes along, the back end doesn’t need to do anything, just use the same set of apis as before

Disadvantages:

  1. You need to manipulate the DOM frequently
  2. Is not conducive to SEO
  3. Throughout the process, there are templates for pages on the back end (template engines), and the front end requests the templates and data, populates the template with data, and presents it to the user
  4. In this process, the route is still controlled by the back end
Single page rich application
  • SPA (Single Page application) The entire process, only one page

  • In this case, the route maintains the mapping between urls and components

  • When the route changes, the front-end automatically loads the corresponding component module

    The front end only needs the back end to request the required data, in a real sense to achieve the separation of the front end and the back end

In this case, routes are completely controlled by the front end, so the routes are called front-end routes

Front-end routing is essentially changing the URL path in some way to display different content, but the page doesn’t refresh while the URL changes

Route implementation method

  • The URL hash
    • The HASH of the URL, also known as the anchor point (#), essentially changes the href attribute of window.location
    • You can change the href by assigning location.hash directly, but the page does not refresh
    • The advantage of Hash is that it is more compatible and can run in older Versions of IE
    • But the flaw is that the URL has a # in it that doesn’t look like a real path
  • It’s history
    • The History interface is a new addition to HTML5
    • Pages that use history mode must be opened using the server and are not supportedfileThe URL at the beginning of the protocol
    • It has six modes to change the URL without refreshing the page
methods instructions
ReplaceState method Replace the original path, no new browsing record is generated
PushState method Using a new path is like adding a new browsing record
Popstate event The PopState event is emitted when the active history entry is changed except for the history.pushState() or history.replacEstate () methods
Go way Change the path forward or backward, parameter is a number, can jump to any page

If the parameter is 0, the current page is refreshed

If the forward and backward values are greater than the values in the existing historical records, no operation is performed and no error is reported
The forward method Changing the path forward is the same thing as going (1).
The back way Changing the path backwards is the same thing as go(-1).

hash

<! DOCTYPEhtml>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
  <title>The URL hash</title>
</head>
<body>
  <div id="app">
    <! Routing -- -- - >
    <a href="#/home">Home</a>
    <a href="#/about">About</a>

    <! -- placeholder -->
    <div id="content">Home</div>
  </div>

  <script>
    const contentElem = document.getElementById('content')

    // Listen to the route change function - the page is not refreshed when the route changes
    window.addEventListener('hashchange'.() = > {
      // location.hash - The hash value can be retrieved with the hash tag
      switch(location.hash) {
        case '#/home':
          contentElem.innerHTML = 'Home'
          break

        case '#/about':
          contentElem.innerHTML = 'About'
          break}})</script>
</body>
</html>
Copy the code

history

<! DOCTYPEhtml>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <! Routing -- -- - >
    <a href="/home">Home</a>
    <a href="/about">About</a>

    <! -- placeholder -->
    <div id="content">Home</div>
  </div>

  <script>
    const contentElem = document.getElementById('content')

    const aEls = document.getElementsByTagName('a')

    const changeRouter = () = > {
      switch(location.pathname) {
        case '/home':
          contentElem.innerHTML = 'Home'
          break

        case '/about':
          contentElem.innerHTML = 'About'
          break}}for (const aEl of aEls) {
      aEl.addEventListener('click'.e= > {
        // Prevent default behavior
        e.preventDefault()

        // Set the history and change the URL -- no jump will occur
        /* An object that can be used to store data that needs to be passed across multiple pages. This object can be obtained using history.state. The initial value is null, which becomes the value passed in when pusState or replaceState is used. 3. The new URL must be in the same domain as the current page. The browser's address bar will display the url */
        history.pushState({}, ' ', aEl.getAttribute('href'))
        changeRouter()
      })
    }

    // When you click the back and forward keys, you also need to re-render the corresponding content
    /* 1. The popState event is emitted when the active history entry changes. 2. Calling history.pushState() or history.replacEstate () does not trigger the popState event 3. Event names are all lowercase 4. This event is on window 5. There is no pushState event */
    window.addEventListener('popstate', changeRouter)
  </script>
</body>
</html>
Copy the code

vue-router

The three most popular front-end frameworks have their own routing implementations:

  • Presents the ngRouter
  • The React of ReactRouter
  • Vue Vue – the router

The installation

#Install - the current default installation is 3.x
npm i vue-router

#The latest version is the 4.x version
npm i vue-router@4
Copy the code

Early experience

Steps to use vue-Router:

  • Step 1: Create a component of the routing component;
  • Step 2: Configure route mapping: Routes array for component and path mapping relationship.
  • Step 3: Create a route object with createRouter and pass in the Routes and History modes.
  • Step 4: Use route: Pass<router-link>and<router-view>

Our routes are stored in the SRC /route folder

Our routing components are usually stored in the SRC /pages or/SRC /views folder

src/routes/index.js

import Home from '.. /pages/Home.vue'
import About from '.. /pages/About.vue'

import {
  createRouter,
  createWebHistory, Call this method if you want to use history mode
  createWebHashHistory // Call this method if hash mode is required
} from 'vue-router'

// Define mapping table -- Route -- Route[]
const routes = [
  {
    path: '/home'./ / path
    component: Home / / component
  },

  {
    path: '/about'.component: About
  }
]

// Define a routing object to store the routing table -- router
export default createRouter({
  routes, / / the routing table
  history: createWebHistory()
})
Copy the code

src/main.js

import { createApp } from 'vue'
import App from './App.vue'

// Import router - The router can be used as a plug-in for VUE
import router from './routes'

The // use method is used to register plug-ins, and the return value is also an app object
createApp(App).use(router).mount('#app')
Copy the code

App.vue

<template>
  <div>
    <! Router-link is a built-in component provided by vue-router. Router-link can be used to jump routes.
    <router-link to="/home">Home</router-link>
    <router-link to="/about">About</router-link>

    <! Router-view is a built-in component provided by vue-router that can be used as a placeholder for content to be displayed.
    <router-view />
  </div>
</template>
Copy the code

The default path

By default, when entering the home page of a website, we expect

to render the contents of the home page

Implementation Method 1

const routes = [
  { // The Home page matches the display content set to the Home component
    path: '/'.component: Home
  },

  {
    path: '/home'.component: Home
  },

  {
    path: '/about'.component: About
  }
]
Copy the code

Implementation 2

const routes = [
  { // If it is the home page, it automatically jumps to /home
    // The path is /home, so it matches the display of the home component
    path: '/'.redirect: '/home'
  },

  {
    path: '/home'.component: Home
  },

  {
    path: '/about'.component: About
  }
]
Copy the code

The router – the link properties

attribute instructions
to Jump path

It can be a string, or it can be an object
replace With the replace attribute, when clicked, router.replace() is called instead of router.push().
active-class Sets the class to be applied after activating element A

Router-link-active exists when the route is matched

Default is the router – link – active
exact-active-class Links are precisely activated when applied to renderThe class

Router-link-exact -active exists only when the routes are matched completely

Default is the router – link – the exact – active
<! -- Use of replace -->
<router-link to="/home" replace>Home</router-link>
<router-link to="/about" replace>About</router-link>
Copy the code
<! Router-active --> router-link-active --> router-link-active
<router-link to="/home" active-class="router-active">Home</router-link>
<router-link to="/about" active-class="router-active">About</router-link>
Copy the code

Exact -active-class and active-class

Assume the following route configuration

import {
  createRouter,
  createWebHistory,
} from 'vue-router'

const routes = [
  {
    path: '/about'.component: () = > import('.. /pages/About.vue'),

    children: [{path: 'info'.component: () = > import('.. /pages/Info.vue'}]}]export default createRouter({
  routes,
  history: createWebHistory()
})
Copy the code

There are two router-links

<router-link to="/about">About</router-link>

<router-link to="/about/info">About</router-link>
Copy the code

When the route is /about

<! -- Router-link-active and router-link-exact -- active
<router-link to="/about">About</router-link>

<! -- existing style is empty -->
<router-link to="/about/info">About</router-link>
Copy the code

When the route is /about/info

<! Router-link-active --> router-link-active
<router-link to="/about">About</router-link>

<! -- Router-link-active and router-link-exact -- active
<router-link to="/about/info">About</router-link>
Copy the code

Route lazy loading

JavaScript packages can become very large when packaged to build applications, affecting page loads

We need to be able to divide the components corresponding to different routes into different code blocks and load the corresponding components only when the routes are accessed, which will be more efficient and improve the rendering efficiency of the first screen

In this case, lazy route loading is required. The Vue Router supports dynamic component import by default

{
  path: '/home'.// Component can pass in a component, or it can receive a function that returns a Promise
  The import function itself returns a promise
  component: () = > import('.. /pages/Home.vue')}, {path: '/about'.// The default folder is chunk-[hash].js
  // If you need to specify the name of the chunk to be packaged manually, you can specify it manually using magic annotations (WebPack will recognize and parse it).
  component: () = > import(/* webpackChunkName: "home-chunk" */'.. /pages/Home.vue')}Copy the code

Other attributes of route

  {
    path: '/home'.name: 'home'.// The unique name of the routing record
    meta: {}, // Custom data
    component: () = > import('.. /pages/Home.vue')}Copy the code

Dynamic routing

Many times we need to map routes with a given matching pattern to the same component

  • We might have a User component that should render all the users, but the ids of the users are different
  • In the Vue Router, we can use one in the pathDynamic fields (variables)Let’s call thatPath parameter (Params parameter)
  • In a pathPath parameters can be multiple

routing

 {
    // Use path parameters -- Multiple path parameters can be used
    path: '/user/:name/id/:id'.component: () = > import('.. /pages/User.vue')}Copy the code

router-link

<router-link to="/user/coderwxf/id/1810100? foo=baz">User</router-link>
Copy the code

user.vue

<template>
  <div>
    User
    <p>name: {{ $route.params.name }}</p>
    <p>id: {{ $route.params.id }}</p>
    <p>query: {{ $route.query.foo }}</p>
  </div>
</template>

<script>
// Vue-router4.x method
import { useRoute } from 'vue-router'

export default {
  name: 'User'.created() {
    // In the Options API, you can get the current route object by calling this.$route
    // this.$route.query -- query parameter -- default {}
    // this.$route.params -- path parameter -- default {}
    console.log(this.$route)
  },

  setup() {
    // useRoute returns the Route object, which holds the values associated with the current route
    // Use the same method as $route in the Options API
    const route = useRoute()
    console.log(route)
  }
}
</script>
Copy the code

NotFound

For routes that do not match, we usually match to a fixed page, such as the error page on NotFound

// If the page path does not match, the router view will display the 404 component (notFound component).
// (.*) indicates that the preceding value pageMatch can match is an arbitrary string of characters
{
  path: '/:pageMatch(.*)'.component: () = > import('.. /pages/NotFound.vue')}Copy the code

NotFound.vue

<template>
  <div>
    <h2>Not Found</h2>
    <! -- pageMatch This parameter depends on the name of the path parameter set in the route -->
    {{ $route.params.pageMatch }}
  </div>
</template>
Copy the code
// The last * indicates that the retrieved query string is split into slashes
// Here is an example
// When * is not added -- home/config/user/info
// add * -- ["home", "config", "user", "info"]
{
  path: '/:pageMatch(.*)*'.component: () = > import('.. /pages/NotFound.vue')}Copy the code

Nesting of routes

The routes that we click on directly in the page are commonly referred to as level 1 routes, such as \home, etc

However, we can still use our routing to display different components inside the components displayed according to the route. This route is called the secondary route, such as \home\config

router.js

  {
    path: '/home'.component: () = > import('.. /pages/Home.vue'),

    // In children we can configure our secondary route
    children: [{// Default /home jumps to /home/config
        path: ' '.redirect: '/home/config'
      },

      {
        path: 'config'.component: () = > import('.. /pages/Config.vue')}, {path: 'version'.component: () = > import('.. /pages/Version.vue')}}]Copy the code

Home.vue

<template>
  <div>
    <router-link to="/home/config">config</router-link>
    <router-link to="/home/version">version</router-link>

    <! -- placeholder -->
    <router-view />
  </div>
</template>
Copy the code
Route replacement rules
{
    path: '/home'.component: () = > import('.. /pages/Home.vue'),

    children: [{The // path is converted to /home/config
        path: 'config'.component: () = > import('.. /pages/Config.vue')}, {// The path is converted to /config
        path: '/config'.component: () = > import('.. /pages/Config.vue')}, {The // path is converted to /home/config
        path: '/home/config'.component: () = > import('.. /pages/Config.vue')},]}Copy the code
<! - assuming that the current site is http://www.example.com/home/config - > 

<! - the current path will be replaced by: http://www.example.com/home/version - >
<router-link to="version">version</router-link>

<! - the current path will be replaced by: http://www.example.com/version - >
<router-link to="/version">version</router-link>

<! - the current path will be replaced by: http://www.example.com/home/version - >
<router-link to="/home/version">version</router-link>
Copy the code

Programmatic routing jumps

Sometimes we want to jump to a page using code, such as clicking a button

Instead of using the router-link component to help us do this, we can implement it in JS code

A route defined by

is called a declarative route

Js route jump — programmatic route

<template>
  <div>
    <button @click="goAbout">Click on me to display the About component</button>
    <button @click="gotoAbout">Click on me to display the About component</button>

    <router-view />
  </div>
</template>

<script>
import { useRouter } from 'vue-router'

export default {
  name: 'App'.methods: {
    goAbout() {
      // options api
      this.$router.push('/about')}},setup() {
    // composition api

    // tips: The useRouter and useRoute functions must be created in the setup top-level scope
    // Cannot be created in a function
    
    // useRouter returns the same router as $router in the Options API
    const router = useRouter()

    const gotoAbout = () = > {
      router.push('/about')}return {
      gotoAbout
    }
  }
}
</script>
Copy the code

Parameters are added

// The resulting jump path ==> /about? name=Klaus&age=24
router.push({
  path: '/about'.query: {
    name: 'Klaus'.age: 24}})Copy the code

Router-link can also pass objects as parameters

<router-link :to="{ path: '/about', query: { name: 'Klaus', age: 24 } }">
  About
</router-link>
Copy the code

Whether it’s in Hash mode or history mode,

All methods on the history object in H5 are available on the Router object

// replaceState
router.replace('/about') // Relative to 
      
       ... 
      

// go -- when no arguments are passed, the default argument is 0
// If the jump path is out of the historical debug - silent failure - no error reported and no effect
router.go(1)
router.go(0)
router.go(-1)

// back === go(-1)
router.back()

// forward === go(1)
router.forward()
Copy the code

Tips:

In hash mode, the root path is converted to http://localhost:8080/#/

In history mode, the root path is converted to http://localhost:8080/

It is recommended to use the history mode in development because it is closer to the normal URL path