Vue routing
What is a SPA
SPA is short for Single Page application, which translates as single page application. Simply put, SPA is a Web project with only one HTML page. Once the page is loaded, SPA will not reload or jump the page due to the user’s operation. Instead, JS is used to transform the HTML content dynamically to simulate the jump between multiple views.
The emergence of front-end routing
With the emergence of AJAX technology, SPA gradually evolved, and the emergence of SPA has greatly improved the user experience. In user interaction, there is no need to refresh the page, and data is obtained asynchronously through AJAX technology, making the page presentation more smooth.
However, since the user interaction in SPA is realized by changing the HTML content with JS, the URL of the page itself does not change, which leads to two problems:
- 1. SPA cannot record the user’s forward and backward operations
- 2. In SPA, there will be a variety of pages to display, but only one page
URL
Is not user friendly, you have to re-click the page you want to go to every time you refresh the page - 3, there is no unified concept of path-page, page management is complex, and it is not friendly to maintain
Front-end routing is used to solve the above problems, such as vue-router and react-router
Vue-router
Front-end routing is a path manager. Generally speaking, VUe-Router is a link path management system of WebApp. The single-page application of VUE is based on routing and components. Routing sets the access path, which corresponds to the URL of the page, and maps the path to the component. Traditional page applications use hyperlinks to switch and jump pages. In vue-Router, it is switching between paths, that is, switching between components. The essence of routing module is to establish the mapping relationship between URL and page, which is realized through URL when refreshing, advancing and retreating.
Why not use the A tag: Since vue is a single-page application that has only one main index.html, the A tag doesn’t work and you have to use vue-Router to manage it.
The principle of
Simply put, there is only one HTML page that matches a route (access path) for each component. Instead of updating the entire page when a user refreshes, forwards, backwards, or jumps, only one component is updated based on the route. To meet the above requirements, we meet the following two core requirements:
- 1, change,
url
Instead of letting the browser send a request to the server. - 2, can listen to the URL changes, and perform the corresponding operations (such as component switch)
There are two modes that do this: hash mode and History mode
Hash pattern
Vue-router uses hash mode by default: uses the characters following the # after the URL. For example www.baidu.com/#aaaa where #aaaa is the hash value we want. Why hash can be used:
- 1.
hash
The change in value does not cause the browser to send a request to the server and does not cause a page refresh. - 2,
hash
A change in value is triggeredhashchange
The event - 3,
hash
Value changes are also recorded in the browser’s historyback
Button to go back to the previous onehash
value
Before the emergence of the HISTORY mode of H5, the hash mode was basically used to realize front-end routing
The history mode
Browsers had history objects before HTML5. But it can only be used for page hopping
history.go(n)
// Forward or backward, n represents the number of pages, and a negative number represents backwardhistory.forward()
// Move forward one pagehistory.back()
// Go back one page
In HTML5, History has the following new API
history.pushState()
// Add a new state to the history stackhistory.replaceState()
// Modify the current item in the history stackhistory.state
// Returns the current state object
PushState and replaceState both accept three parameters (state,title, URL)
state
: a valid JS object that can be used in thepopstate
In the eventtitle
: Most browsers ignore this parameter and can pass null placeholdersurl
: Any valid URL (must be the same as the current URL, otherwise an exception will be thrown) used to update the browser URL. In the callpushState
orreplaceState
A new history with the new URL is immediately generated (the current URL has become the most recent), but the browser does not load the URL immediately (the page is not refreshed) and may load the URL later in certain circumstances, such as when the user reopens the browser or presses enter in the address bar.
The difference between pushState and replaceState is that:
pushState
Records with new urls are added to the history stack while the existing history is retained.replaceState
Will place the current page in the history stackThe state, url
Replace with the latest
Because the pushState and replaceState methods can change the current URL without refreshing the page, they can be used to implement front-end routing.
However, since calls to pushState and replaceState do not trigger events (popState events are only triggered when the user manually clicks the forward or back buttons or calls the go, back, or forward methods in JS), there are two corresponding solutions:
- 1. Click the forward and back buttons or in the
js
In the callGo, back, forward
Method: Listenpopstate
Event in the event callback based on the currenturl
Render the corresponding page. - 2, when the need to jump path (call
push
Method: first render the corresponding page according to the path, and then pass after the page rendering is completedpushState
orreplaceState
Method to update the browser URL.
This implements front-end routing for history mode
After history changes the URL, the page will not refresh, but after we manually refresh the page, the browser will send a request to the server with the current URL, but because we only have one HTML file, the browser will process other paths, the situation will be 404. At this point, you need to add a candidate resource on the server that covers all cases: if the URL does not match the static resource, the HTML file of the single-page application is returned. This leaves it entirely up to the front end to handle the routing.
Select hash and history modes
Hash advantages:
- 1, good compatibility, compatible with IE8
- 2. Single-page applications can be processed without any configuration on the server
Disadvantages:
- 1. The path is ugly
- 2. The anchor point function will fail
- 3. The same
hash
The history stack is not updated
The history advantages:
- 1. The path is better
- 2, the anchor function is available
- 3,
pushState
You can add the same record to the history stack
Disadvantages:
- 1, poor compatibility, not compatible with IE9
- 2. Server support is required
Vue – the use of the router
-
1. Open CMD command NPM install vue-router to install the routing module of vUE
-
2. Introduce vue.js first and then vue-router.js, because vue-router is based on VUE. Vue.use(plugin) installs VueRouter using the plugins provided by vue.js. The purpose of this is not to rely on the Vue version, the two versions can be used interchangeably. This plug-in mechanism works by calling the install method of the plug-in (if there is no install method, the passed plug-in is called as a function).
import Vue from 'vue'
import VueRouter from 'vue-router'
// Pass VueRouter as a plug-in: the purpose is not to rely on vue, you can mix versions, or you can just use VueRouter
Vue.use = function(plugin, options){
plugin.install(this, options)
}
Vue.use(VueRouter) // The plugin's install method is called and the Vue is passed in
Copy the code
Install.js does the following:
- 1, the introduction of
Vue
Save it for later use - 2. Inject the root component into each component, ensuring that each
Vue
Can get the Router attribute on the root component - 3, to achieve the route response type principle, the root component on the
_route
Properties are defined as responsive data, such that_route
Properties change to update the view - 4. Initialize the route
- 5. Register the global routing component
// install.js
import View from './components/view'
import Link from './components/link'
export let _Vue
export function install(Vue){
_Vue = Vue
// The root component is injected into each component in the manner of mixins
Vue.mixin({
beforeCreate(){
// The router attribute is the root component
if(this.$options.router){
this._routeRoot = this
this._router = this.$options.router
/* Init should be placed before defineReactive. History. current is the record of the route corresponding to the current URL. Then we just need to update the view */ by defining the reactive attribute _route on the root component pointing to the latest routing record
this._router.init(this)
Vue.utils.defineReactive(this.'_route'.this._router.history.current)
} else {
this._routeRoot = this.$parent && this.$parent._routeRoot || this}}})// Add a property broker to facilitate the use of property routing properties in components
Object.defineProperty(Vue.property, '$route', {get(){
return this._routeRoot._route
}
})
Object.defineProperty(Vue.property, '$router', {get(){
return this._routeRoot._router
}
})
Vue.component('RouterView', View)
Vue.component('RouterLink', Link)
}
Copy the code
Instantiation VueRouter
- 1. Declare to create a routing table and associate paths with corresponding components in the routing table
- 2. Create a route instance, initialize the route, and import the route to the routing table
- 3. Register routes in vUE instances
import App from './App'
let Home = { template:'< div > home page < / div >' };
let List = { template:
List page
};
// create a route instance
let router = new VueRouter({// Initialize the route: pass in the routing table
mode: 'history'.// Back end support is required
routes: [// First level path must be preceded by '/'
{ path: '/'.component:Home },// Routes displayed by default (default routes displayed do not need to add /)
{ path: '/home'.component:Home },// One path corresponds to one component
{ path: '/list'.component:List },
{ path: The '*'.redirect:'/home' }// Redirects to the home component when the user enters a random path, preventing 404 from appearing
] / / es6 shorthand
});
//2. Inject the routing instance into the vue root instance and then use it in the page
new Vue({
el:'#app',
router, // Inject routing (ES6 abbreviation)
render: h= > h(App)
})
Copy the code
// vue route SRC /index.js
export default class VueRouter {
// The corresponding history instance will be generated based on the corresponding schema and mounted on the current class instance
init(app){ // This is the instance of the root component passed in when router.init is called in install.js
const history = this.history
const setupListener = () = >{
// It is convenient to add some other operations
history.setupListener()
// todo...
}
// Get the current path, call the transitionTo method, and match the path to the corresponding route.
history.transitionTo(history.getCurrentLocation(), setupListener)
history.listen(route= >{
/* Because in install.js the _route attribute of the root (app) component is already defined for reactive vue.util.definereactive (this, '_route', This._router.history.current) so just update the data to drive the view update */
app._route = route
})
}
}
Copy the code
router-view
Router-view (Global component: used to render routing components) Router-view is used as a global component in the page to render routing pages to the page
<div id="app">
<router-view></router-view>
</div>
Copy the code
router-link
Use the router-link global component for click-to-jump
Router-link has two properties:
to
: Which path to jump to (must be added, value is the path to jump to)tag
: want torouter-link
Which label to change (default isa
The label)
<! Modify the above HTML as follows -->
<div id="app">
<router-link to="/home" tag="button">Home page</router-link>
<router-link to="/list" tag="button">List of pp.</router-link>
<! -- if you want params as an object and you want params as an object, you can only jump with name (ptah) -->
<router-link :to="{name:'list',params:{userId:1}}" tag="button">List of pp.</router-link>
<router-view></router-view>
</div>
Copy the code
Routing information and methods
After routing is registered in an instance of vue, each vue component instance can obtain the _router and _route attributes on the root component by obtaining the $router and $route attributes (because install.js was already proxy when vue. use was injected).
$route
: Route information object, which represents the status information of the current active route, including the information about the current URL resolution and the records of the routes matched by the URL$router
: an instance of the current route, with various hop methods on the prototype
$router
this.$router.push()
: Forcibly jumps to a path. The parameter is paththis.$router.replace()
: Route replacement, replacing the current path with a new one (rarely used)this.$router.go()
: Returns a level. The parameter is how many levels to return (-1 is the upper level, 1 is the lower level)
$route
The currently active routing information object. This property is read-only, and the properties inside it are immutable, but it is possible to watch it.
$route.path
: a character string corresponding to the path of the current route, which is always resolved to an absolute path, such as/foo/bar
.$route.params
A:key/value
Object, containing dynamic fragments and fully matched fragments, is an empty object if there are no routing parameters.$route.query
A:key/value
Object, representingURL
Query parameters. For example, for paths/foo? user=1
, there are$route.query.user == 1
, is an empty object if there are no query parameters.$route.hash
: indicates the current routehash
Value (with#
) if nothash
Value is an empty string.$route.fullPath
: after parsingURL
Contains query parameters andhash
The full path to.$route.name
: Indicates the name of the current route, if any.$route.redirectedFrom
: If redirection exists, it is the name of the route from which the redirection originated.
// Since there are many paths and we cannot write them to death, we need to write them in a regular form to match paths
/article/2/d // a path
/article/:c/:a {c:2,a:d} $route.params {c:2,a:d}
Copy the code
Nesting of routes
Second-level routes can be nested in the routing table. The template of the first-level route that is nested with second-level routes needs to be modified accordingly.
<div id="app">
<router-link to="/home">Home page</router-link>
<router-link to="/detail">Details page</router-link>
<router-view></router-view><! Level 1 Routing display area -->
</div>
<template id="detail">
<div>
<router-link to="/detail/info">Personal center</router-link>
<router-link to="/detail/about">About me</router-link>
<router-view></router-view><! -- Secondary route display area -->
</div>
</template>
Copy the code
/ / component
let home={template:'<div>home</div>'};
let detail={template:'#detail'};
let info={template:'<div>info</div>'};
let about={template:'<div>about</div>'};
// Create a routing table
let routes=[
{ path:'/home'.component:home },
{
path:'/detail'.component:detail,
// The secondary route is written in the childern attribute
children: [// The path of level-2 or higher routes should never contain '/'. If the path contains'/', it indicates level-1 routes
{ path:'info'.component:info },
{ path:'about'.component:about }
]
},
];
// Initializes the route and passes it to the routing table
let router = new VueRouter({
mode: 'history',
routes
});
let vm = new Vue({
el:'#app'.// Register the route
router
})
Copy the code
Dynamic routing
Methods to be used:
router.beforeEach
:vue-router
The provided navigational guard is mainly used to guard navigation by jumping or canceling. There are several opportunities for embedding route navigation: global, single route proprietary, or component level.router.addRoutes()
: Dynamic mount route (the function of this method is only in the path to see the corresponding page, but the menu display is required), the parameter must be a matchroutes
An array of options required
Next (‘/’) or next({path: ‘/’}): {path: ‘/’}): {path: ‘/’}): {path: ‘/’}); redirect to a different location. The current navigation will be aborted and a new one will be started.
In this way, we can easily avoid the previous problem by next(to). This line re-enters the route. beforeEach hook function and releases the hook with next() to ensure that all routes are mounted.
The router index. Js file
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
// Create a static routing table
export const constantRouterMap = [
{ path: '/ 404'.component: () = > import('@/views/404'), hidden: true },
{
path: '/'.component: Layout,
redirect: '/home'.name: 'Home'.children: [{
path: 'home'.component: () = > import('@/views/home/index'),
meta: { title: 'home'.icon: 'home'}}}]]// Initialize the route to the static routing table and export it
export default new Router({
mode: 'history'.// Use history mode
scrollBehavior: () = > ({ y: 0 }),
routes: constantRouterMap
})
// All routes (dynamic routing table that needs to be filtered, add items directly here later, filter table according to permissions after dragging permission)
export const asyncRouterMap = [
// Permission management
{
path: '/access'.component: Layout,
name: 'access'.children: [{path: 'index'.name: 'access/index'.component: () = > import('@/views/access/index'),
meta: { title: 'Permission Management'.icon: 'lock'}}},// Operation background
{
path: '/operation'.component: Layout,
name: 'operation'.meta: {
title: 'Back office'.icon: 'operation'
},
children: [
// Inke Live
{
path: 'live'.component: () = > import('@/views/operation/index'), // Parent router-view
name: 'operation/live'.meta: { title: Inpidlive },
children: [
// Feedback
{
path: 'feedback'.name: 'operation/live/feedback'.component: () = > import('@/views/feedback/index'),
meta: { title: 'Feedback'}}]}]Copy the code
After creating a route, you need to filter the global routing table after obtaining the permission to filter out useless routes.