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:
- Each module of the entire page needs to be written and maintained by the back-end staff
- 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:
- Clear accountability at the front and back ends, with the back end focused on data and the front end focused on interaction and visualization
- 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:
- You need to manipulate the DOM frequently
- Is not conducive to SEO
- 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
- 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 supported
file
The 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 path
Dynamic fields (variables)
Let’s call thatPath parameter (Params parameter)
- In a path
Path 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