introduce
Vue Router is the official route manager of vue.js. Its deep integration with vue.js core makes building single-page applications a breeze. The features included are:
-
Nested routing/view chart
-
Modular, component-based routing configuration
-
Route parameters, queries, and wildcards
-
View transition effect based on vue. js transition system
-
Fine-grained navigation control
-
Links with automatically activated CSS classes
-
HTML5 historical mode or Hash mode is automatically degraded in IE9
-
Custom scroll bar behavior
start
Creating a single page application with Vue. Js + Vue Router is very simple. With vue.js, we can already compose applications by combining components. When you add a Vue Router, what we need to do is map components to routes and tell the Vue Router where to render them
The installation
npm i vue-router -S
In the main. In js
import Vue from 'vue' import VueRouter from 'vue-router' Vue.use(VueRouter) Copy the code
Recommended use: Vue add Router add-on (remember to submit in advance)
The basic use
router.js
import Vue from 'vue'
/ / 1. Imported
import Router from 'vue-router'
import Home from './views/Home.vue'
import About from './views/About.vue'
//2. Modularity mechanism uses Router
Vue.use(Router)
//3. Create router objects
const router = new Router({
//mode: 'history', //history mode clean page address does not have #/ such symbols exist
routes: [{path: '/home'.component: Home
},
{
path: '/about'.component: About
}]
})
export default router;
Copy the code
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
new Vue({
// 4. Mount root instance
router,
render: h= > h(App)
}).$mount('#app')
Copy the code
After the above configuration is complete
<template>
<div id="app">
<div id="nav">
<! -- Use router-link to navigate -->
<! -- Pass the to attribute to specify the connection -->
<! -- Router-link is rendered as an A tag by default -->
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link> |
<! -- Route exit -->
<! -- Routing matching components will be rendered here -->
<router-view/>
</div>
</div>
</template>
Copy the code
Open your browser and switch between the Home and About hyperlinks to see the effect
After routing
When configuring a route, add a name to the route so that access can be dynamically performed based on the name
const router = new Router({
routes: [{path: '/home'.name: 'home'.component: Home
},
{
path: '/about'.name:'about'
component: About
}]
})
Copy the code
To link to a named route, pass an object to router-link’s to property:
<router-link :to="{name:'home'}">Home</router-link> |
<router-link :to="{name:'about'}">About</router-link> |
Copy the code
Dynamic Route Matching
We often need to map all the routes that a pattern matches to the same component. For example, we have a User component that is used to render for all users with different ids. We can use dynamic segments on vue-Router routes to achieve this effect
User.vue
<template>
<div>
<h3>The user page</h3>
</div>
</template>
<script>
export default{};</script>
<style lang="scss" scoped>
</style>
Copy the code
The routing configuration
const router = new Router({
routes: [{path: '/user/:id'.name: 'user'.component: User,
}]
})
Copy the code
<router-link :to="{name:'user',params{id:1}}">User</router-link> |
Copy the code
See the effect
When a route is matched, the parameter value is set to this.$route.params, which can be used in each component, so we can update the User template to print the current User ID:
<template>
<div>
<h3>{{$route.params.id}}</h3>
</div>
</template>
Copy the code
Responds to changes in routing parameters
As a reminder, when routing parameters are used, such as navigating from /user/1 to /user/2, the original component instance is reused. Because both routes render the same component, reuse is more efficient than destroying and recreating. However, this also means that the component’s lifecycle hooks are no longer called.
To respond to changes in routing parameters when reusing components, you can simply watch the $route object:
$route object watch: {$route(to, from) {console.log(to.params.id); }}, * /
// Or use the navigation guard
beforeRouteUpdate(to,from,next){
// View route changes
// Next must be called, otherwise route changes will be blocked
next();
}
Copy the code
404 routing
const router = new Router({
routes: [//....
// If no route is matched, the 404 page is displayed
{
path: The '*'.component: () = > import('@/views/404')}]})Copy the code
When using wildcard routes, ensure that the order of routes is correct, that is, routes containing wildcards should be placed last. The route {path: ‘*’} is usually used for client 404 errors
When a wildcard is used, $route.params automatically adds a parameter named pathMatch. It contains parts of the URL that are matched by wildcards:
{
path: '/user-*'.component: () = > import('@/views/User-admin.vue')}this.$route.params.pathMatch // 'admin'
Copy the code
Matching priority
Sometimes, the same path can match multiple routes. In this case, the priority of the matched routes is the highest according to the route definition order: the one defined first has the highest priority.
Query parameters
Like address that appear on this: http://localhost:8080/page? id=1&title=foo
const router = new Router({
routes: [/ /...
{
path: '/page'.name: 'name'.component:() = > ('@/views/Page.vue')}]})Copy the code
<router-link :to="{name: 'page', query:{id: 1, title: 'foo'}}">User</router-link>
Copy the code
Go to http://localhost:8080/page? Id = 1 & title = foo view the Page
Page.vue
<template>
<div>
<h3>Page Page</h3>
<h3>{{$route.query.userId}}</h3>
</div>
</template>
<script>
export default {
created () {
// View the routing information object
console.log(this.$route); }},</script>
<style>
</style>
Copy the code
Route redirection and alias
redirect
Example redirects from/to /home:
const router = new Router({
mode: 'history'.routes: [
/ / redirection
{
path: '/'.redirect: '/home'
},
{
path: '/home'.name: 'home'.component: Home
},
]
})
Copy the code
The redirection target can also be a named route:
const router = new VueRouter({
routes: [{path:'/'.redirect: {name: 'name'}}}])Copy the code
The alias
{
path: 'user/:id'.name: 'user'.component: User,
alias: '/alias'
}
Copy the code
The “alias” feature gives you the freedom to map UI structures to arbitrary urls, rather than being constrained by configuration nested structures.
Route component parameters are transmitted
Using $route in a component makes it highly coupled to its corresponding route, limiting its flexibility by limiting its use to certain urls.
Decouple components and routes using props:
Replace coupling with $route
Index.js
{
path: '/user/:id'.name: 'user'.component: User,
//props: true
//props can also be a function
props: (route) = > {
id: route.params.id,
title: route.query.title
}
}
Copy the code
User.vue
<template>
<div>
<h3>{{$route.params.id}}</h3>
<h3>User page {{id}}</h3>
</div>
</template>
<script>
export default{
//....
props: {
id: {
type: String.default: ' '}},}</script>
Copy the code
Props can also be a function
User.vue
<template>
<div>
<h3>{{id}}-{{title}}</h3>
</div>
</template>
<script>
export default {
// ...
props: {
id: {
type: String.default: ' '
},
title: {type: String}}};</script>
Copy the code
Programmatic navigation
In addition to using
to create a tag to define navigation links, we can also use the router instance method. By writing code.
Note: Inside the Vue instance, you can pass
The router. Push.
declarative | programmatic |
---|---|
<router-link :to="..." > |
router.push(...) |
The argument to this method can be a string path or an object describing the address. Such as:
/ / string
this.$router.push('home')
/ / object
this.$router.push({path: 'home'})
// Named route
this.$router.push({name: 'user'.params: {userId}: '123'})
// With query parameters, change to /register? plan=private
this.$push({path: 'register'.query: {plan: 'private'}})
Copy the code
Move back
// Further forward in the browser record, equivalent to history.forward()
router.go(1)
// Step back to record, equivalent to history.back()
router.go(-1)
// Forward 3 steps record
router.go(3)
// If the history is insufficient, the default is failure
router.go(-100)
router.go(100)
Copy the code
Embedded routines by
/user/1/profile /user/1/posts +------------------+ +-----------------+ | User | | User | | +--------------+ | | +-------------+ | | | Profile | | +------------> | | Posts | | || || || || | +--------------+ | | +-------------+ | +------------------+ +-----------------+Copy the code
router.js
{
path: '/user/:id'.name: 'user'.component: User,
props: ({params,query}) = >({
id: params.id,
title:query.title
}),
children: [// If /user/:id/profile matches successfully,
// The Profile will be rendered in the User's
{
path:"profile".component: Profile
},
// if /user/:id/posts matched successfully,
// Posts will be rendered in User's
{
path: "posts".component: Posts
}
]
}
Copy the code
Add a
to the User component template:
<template>
<div>
<h3>{{$route.params.id}}</h3>
<h3>User page {{id}}</h3>
<router-view></router-view>
</div>
</template>
Copy the code
App.vue
<template>
<div id='app'>
<! -- Nested routine by -->
<router-link to="/user/1/profile">User/profile</router-link> |
<router-link to="/user/1/posts">User/posts</router-link> |
</div>
</template>
Copy the code
Named view
Named views come in handy when you want to show multiple views at the same time (sibling) instead of nesting them, such as creating a layout that has sidebar (side navigation) and main (main content) views.
{
path: '/home'.name: 'home'.// Note that this key is components
components: {
default: Home, // The default name
main: () = >import('@/views/Main.vue'),
sidebar: () = >import('@/views/Sidebar.vue')}}Copy the code
App.vue
<router-view/>
<router-view name='main'/>
<router-view name='sidebar'/>
Copy the code
Navigation guard
Navigation indicates that the route is changing.
Complete navigation parsing process
-
Navigation is triggered.
-
Call the leave guard in the inactivated component.
-
Call the global beforeEach guard
-
Call the beforeRouterUpdate guard (2.2+) in the reused component.
-
Call beforeEnter in routing configuration.
-
Parse the asynchronous routing component.
-
Call beforeRouterEnter in the active component.
-
Call the global beforeResolve guard (2.5+).
-
Navigation confirmed.
-
Call the global afterEach hook.
-
Trigger a DOM update.
-
Call the callback function passed to Next in the beforeRouterEnter guard with the created instance.
Global guard
You can register a global front-guard using router.beforeEach
const router = newVueRouter({... }) router.beforeEach((to, form, next) = > {
/ /...
})
Copy the code
There is a demand, the user access in browsing the site, will visit many components, when the user to jump to/notes, found that the user is not logged in, should allow the user to log in to view at this time, should allow the user to jump to the login page, login to finish before he can see the contents of my notes, at this time of global guard has played a key role.
There are two routes /notes and /login.
router.vue
const router = new VueRouter({
routes: [{path: '/notes'.name: 'notes'.component: () = > import('@/views/Notes')}, {path: '/login'.name: 'login'.component: () = > import('@/views/Login')]}})// Global guard
router.beforeEach((to, from, next) = > {
// The user is accessing '/notes'
if(to.path === '/notes') {
// Check whether the user has saved the login status information
let user =
JSON.parse(localStorage.getItem('user'))
if(user) {
// If yes, go ahead
next();
}else {
// If no, go to the login page to log in
next('/login')}}else{ next(); }})Copy the code
Login.vue
<template>
<div>
<input type="text" v-model="username">
<input type="password" v-model="pwd">
<button @click="handleLogin">submit</button>
</div>
</template>
<script>
export default {
data() {
return {
username: "".pwd: ""
};
},
methods: {
handleLogin() {
//1. Obtain the user name and password
//2. Interact with the backend
setTimeout(() = > {
let data = {
username: this.username
};
// Save the user login information
localStorage.setItem("user".JSON.stringfy(data));
// Jump to my notes page
this.$router.push({name: "notes"});
}, 1000); }}},</script>
Copy the code
App.vue
<! -- Global Guard demo --><router-link to="/notes">My notes</router-link> |
<router-link to="/login">The login</router-link> |
<button @click="handleLogout">exit</button>
<script>
export default {
methods: {
handleLogout() {
// Delete login status information
localStorage.removeItem("user");
// Jump to the home page
this.$router.push('/')}}}</script>
Copy the code
Guards within components
You can define the following route navigators directly within the routing component:
beforeRouteEnter
beforeRouteUpdate
(2.2 Added)beforeRouteLeave
<template>
<div>
<h3>User edit page</h3>
<textarea name id cols="30" rows="10" v-model="content"</textarea>
<button @click="saveData">save</button>
<div class="wrap" v-for="(item, index) in list" :key="index">
<p>{{item.title}}</p>
</div>
</div>
</template>
<script>
export default {
data() {
return {
content: "".list: [].}},methods: {
saveData() {
this.list.push({
title: this.content
});
this.content = ""; }},beforeRouteLeave(to, from, next) {
// called when navigating away from the component's corresponding route
// Access component instance 'this'
if(this.content) {
alert("Please make sure the information is saved before leaving.");
next(false);
}else{ next(); }}};</script>
Copy the code
The permission control of routing meta information is realized
Set a META field for the route to which you want to add permissions
{
path: '/blog'.name: 'blog'.component:() = > import('@/views/Blog'),
meta: {
requiresAuth: true} {},// Route exclusive guard
path: 'notes'.name: 'notes'.component: () = > import('@/views/Notes'),
meta: {
requiresAuth: true}},Copy the code
// Global guard
router.beforeEach((to, from, next) = > {
if(to.matched.some(record= > record.meta.requiresAuth)) {
// Permissions are required
if(!localStorage.getItem('user')) {
next({
path: '/login'.query: {
redirect: to.fullPath
}
})
}else{ next(); }}else{ next(); }})Copy the code
Login.vue
// Login operation
handleLogin() {
// 1. Obtain the user name and password
// 2. Interact with the backend
setTimeout(() = > {
let data = {
username: this.username
};
localStorage.setItem("user".JSON.stringify(data));
// Jump to the previous page
this.$router.push({path:this.$route.query.redirect });
},1000};
}
Copy the code
Data acquisition
Sometimes, after entering a route, you need to fetch data from the server. For example, when rendering user information, you need to fetch user data from the server. We can do this in two ways:
-
Retrieves after navigation: Completes navigation, then retrieves data in the following component lifecycle hooks. Display instructions such as “loading” during data retrieval.
-
Before the completion of navigation: Before the completion of navigation, data is obtained from the guard entering the route, and navigation is performed after the data is obtained successfully.
Get the data after navigation is complete
When you use this approach, we immediately navigate and render the component, and then get the data in the component’s Created hook. This gives us the opportunity to show one loading state during data fetching and different loading states between different views.
<template>
<div class="post">
<div v-if="loading" class="loading">Loading...</div>
<div v-if="error" class="error">{{ error }}</div>
<div v-if="post" class="content">
<h2>{{ post.title }}</h2>
<p>{{ post.body }}</p>
</div>
</div>
</template>
Copy the code
<script>
export default {
name: "Post".data() {
return {
loading: false.post: null.error: null
};
},
// Get data after component is created.
// Data is already monitored
created() {
// If the route changes, the method is executed again
this.fetchData();
},
watch: {
$route: "fetchData"
},
methods: {
fetchData() {
this.error = this.post = null;
this.loading = true;
this.$http.get('/api/post').then((result) = > {
this.loading = false;
this.post = result.data;
}).catch((err) = > {
this.error = err.toString();
});
}
}
</script>
Copy the code
Expanded content:
Multi-page application MPA each page is an.HTML file
A single page application SPA is equivalent to an A TAB that switches between different views