Vue-Router
brief introduction
Routing is the activity of transmitting information from the source address to the destination address through the interconnected network
Back end Routing: the back end processes the mapping relationship between URL s and pages
With the emergence of the front and rear end separation stage, the single page rich application stage will be reached:
- In fact, the main feature of SPA is to add a layer of front-end routing on the basis of front-end and back-end separation
- That is, the front end maintains a set of rules
When we enter a website, we will download all its resources html+css+js. At this time, we use front-end routing, such as url: own domain name / home url: own domain name / about
At this time, we extract the required resources from all resources, which are components in our vue
In essence, front-end routing is the mapping relationship between url and components. Extracting resources is to extract mapped resources from all resources and render them
Preparation stage
hash of URL
In essence, it is the parameter splicing of the web address, which will not refresh the page and request resources
Can be in the console
location.hash = "home"
pushState in H5
Can be in the console
history.pushState({},'','home');
Here we compare similar stack structures
history.pushState({},'','me');
At the top of the current stack is the me page
Enter history Back() we will return to the home page
replaceState in H5
history.replaceState({},'','home')
history.replaceState({},'','about')
We don't have a back button at this time
go in H5
This is to jump to a stack
history.pushState({},'','home');
history.pushState({},'','me');
history.pushState({},'','about');
history.pushState({},'','test');
history.pushState({},'','demo');
At this time, we enter in the demo page
history.go(-3)
At this time, the stack jumps out of three, and we reach the me page
history.go(2)
At this time, we push two into the stack to reach the test page
So history Back() is equivalent to history go(-1),history. Forward () is equivalent to go(1)
Cognitive configuration
At present, the three popular front-end frameworks have their own routing implementation:
- ngRouter of Angular
- ReactRouter of React
- Vue router of Vue
install
①npm install vue-router --save
② Use it in a modular project (because it is a plug-in, you can install the routing function through Vue.use())
- Import the routing object and call Vue use(VueRouter)
- Create a routing instance and pass in the routing mapping configuration
- Mount the created routing instance in the Vue instance
Build routing framework
The following is the index in our router folder JS routing related configuration
//Configure routing information import Vue from 'vue' import VueRouter from 'vue-router' import Home from '../views/Home.vue' // 1. Call vue Use to install the vue plug-in, provided vue is introduced (line 3) Vue.use(VueRouter) // This is where we configure the url mapping relationship const routes = [ { path: '/', name: 'Home', component: Home }, { path: '/about', name: 'About', // route level code-splitting // this generates a separate chunk (about.[hash].js) for this route // which is lazy-loaded when the route is visited. component: () => import(/* webpackChunkName: "about" */ '../views/About.vue') } ] // 2. Create vueroter object const router = new VueRouter({ routes }) // 3. Pass the router object into the Vue instance export default router
Configure the mapping relationship of routes
- Create routing component
- Configure route mapping: component and path mapping relationship
Index. In the router folder Configuration relationship in JS file
//Import components import Home from "../components/Home" import About from "../components/About" const routes = [ { path:'/home', component:Home }, { path:'/about', component:About } ]
- Using routing: through and
On app In Vue file
<template> <div id="app"> <router-view></router-view> <router-link to="/home">home page</router-link> <router-link to="/about">about</router-link> </div> </template>
Default path for routing
- That is, as soon as you open the web page, you go to a component
Here, we also need to define it in the router,
const routes = [ { path:'/', // Redirect redirect redirect:'/home' } { path:'/home', component:Home }, { path:'/about', component:About } ]
Modify hash mode
"#" will appear when we change the path, as long as we change the mode from hash to history
Set when creating the vueroouter object
// 2. Create vueroter object const router = new VueRouter({ routes, mode:'history' })
use
<router - link>
- tag attribute
By default, our tag will be rendered as a tag, but we can use its tag attribute to change its tag
tag="button" this will become a button
<router-link to="/home" tag="button">home page</router-link>
- replace
Sometimes we don't want the back and forward buttons to appear, so we use the replace tab
- Active class attribute
Modify the default name when clicked, which is very convenient when used in combination with CSS
active-class = "actived"
<router-link to="/home" tag="button" active-class="actived">home page</router-link> <router-link to="/home" tag="button" active-class="actived">about</router-link>
Sometimes we don't want to write active class on a large number of labels, so we can use index JS to modify the default name of the clicked component
const router = new VueRouter({ routes, mode:'history', linkActiveClass:'actived' })
Code implementation routing
<template> <div id="app"> <router-view></router-view> <!-- <router-link to="/home" tag="button" replace>home page</router-link> <router-link to="/about" tag="li" replace>about</router-link> --> <button @click="homeBtn">home page</button> <button @click="aboutBtn">about</button> </div> </template> <script> export default{ name:'App', methods: { homeBtn(){ //The router here is index Variable name const router in JS file //this.$router.push('/home') has a return button this.$router.replace('/home').catch(err=>[]) console.log("home") }, aboutBtn(){ this.$router.replace('/about').catch(err=>[]) console.log("about") }, } } </script>
Dynamic routing
Sometimes we need to load the user interface, and we need to jump according to the user id
First, we need the index Configuring users in JS- Variable names are specified
{ path:'/user/:userId', component:User },
Data in data
data(){ return{ userId:"Joseph" }
In the template, we use v-bind to use variables
<template> <div id="app"> <router-link v-bind:to="/user/+userId" tag="button" replace>my</router-link> <router-view></router-view> </div> </template>
We get data from the parent component and display it in the child component user
User. We show it in the Vue file
<template> <div> <h2>I'm a user</h2> <p>I am the user's relevant information</p> <h3>{{userId}}</h3> <h3>{{$route.params.userId}}</h3> </div> </template> <script> export default { name:"User", computed: { userId(){ // The route obtained here is the route in the active state in the routing table // Active status refers to which component you are currently displaying (using) return this.$route.params.userId } } } </script>
$route is different from $route
The former is for us to obtain our VueRouter, and the latter is for us to obtain the route in the current active state
Lazy loading of routes
Because of our bundle JS resources are too large (because various packaging underlying code transformations are in it). We don't want to open and load resources for a long time, that is, there is a page blank period
- Therefore, if we can divide the components corresponding to different routes into different code blocks, and then load the corresponding components when the routes are accessed, it will be more efficient
Essence: package different routes into different JS files
We just need to write in index JS can modify the writing method of the routing table
const routes = [ { path:'/', redirect: '/home' }, { path:'/user/:userId', //neographism component:()=>import('../components/User') }, { path:'/home', component:()=>import('../components/Home') }, { path:'/about', component:()=>import('../components/About') } ]
Or we define the variable as an imported statement at the beginning
const Home = ()=> import('../components/Home'); const About = ()=> import('../components/About'); const User = ()=> import('../components/User'); const routes = [ { path:'/', redirect: '/home' }, { path:'/user/:userId', component:User }, { path:'/home', component:Home }, { path:'/about', component:About } ]
Nested use of routes
- For example, we can access some content in home/news and home/message
- One path maps to one component, and accessing these two paths will render two components respectively
There are two steps to implement nested Routing:
- Create corresponding sub components and configure corresponding sub routes in route mapping
Here we have created two vue components, HomeNews and HomeMessage, which are introduced as follows
const HomeNews = ()=> import('../components/HomeNews'); const HomeMessage = ()=> import('../components/HomeMessage'); //We add the child of Home in the routing table { path:'/home', component:Home, childern:[ { path:'news', component:HomeNews }, { path:'message', component:HomeMessage } ] }
Note: the sub path here does not need to be preceded by "/" because it is a relative path
- Use labels inside components
Here we need to add tags in the template of the home component
Home. Templates in Vue files
<template> <div> <h2>I'm the home page</h2> <p> I am the content of the home page </p> <router-link to="/home/news" tag="button">Journalism</router-link> <router-link to="/home/message" tag="button">news</router-link> <router-view></router-view> </div> </template>
Note: Here we use the absolute path to
Similarly, we give it a default path to the page
children:[ { path:'', redirect: 'news' }, ... ]
Parameter transfer
- In dynamic routing, we use $route params. Userid, which is the way in which parameters are always passed
There are two main types of parameters we pass: params and quert
-
Type of params
- Configure routing format: / router/:id
- Transfer method: follow the path with the corresponding value (string splicing of the to attribute in the router link tag)
- Paths formed after transfer: / router / 123, / router / ABC
-
query
- Configure routing format: / router, that is, normal configuration
- Transfer method: the key of query is used as the transfer method in the object
- Path formed after transfer: / router?id=123, /router?id=abc
<router-link :to="{path:'/profile',query:{name:userId,age:19,height:1.70}}" tag="button" replace>archives</router-link>
http://localhost:8080/profile?name=Joseph&age=19&height=1.7
URL: protocol: / / host: port / path? Query # fragment
scheme://host:port/path?query#fragment
So how do we get information from query?
this.$route.query, we can get this object
<template> <div> <h2> I am Profile </h2> <span> {{this.$route.query}} </span> </div> </template> <script> export default { name:'Profile' } </script>
Navigation guard
- Sometimes we want to listen to the jump of components. According to the previous method, we will use the life cycle, created, mounted and updated, and the callback function executed when it is created, mounted and updated
- Current requirements: click component, document The title will change. We can call back in the life cycle function, but this will be written in each component
So we use our global navigation guard
First, we need to define metadata (data describing data) meta for each route
const routes = [ { path:'/', redirect: '/home', meta:{ title:'home page' } }, { path:'/user/:userId', component:User, meta:{ title:'user' } }, { path:'/home', component:Home, children:[ { path:'', redirect: 'news' }, { path:'news', component:HomeNews }, { path:'message', component:HomeMessage } ], meta:{ title:'home page' } }, { path:'/about', component:About, meta:{ title:'about' } }, { path:'/profile', component:Profile, meta:{ title:'User profile' } } ]
Then we use the navigation guard
//This is the vueroter object const router = new VueRouter({ routes, mode:'history', linkActiveClass:'actived' }) //Front hook and guard (need to actively call next() function) router.beforeEach((to,from,next)=>{ //Code to implement requirements document.title = to.meta.title //This next() must be written. If it is not written, all components in the router cannot jump //After calling this method, you can enter the next hook next(); //Sometimes we don't want users to jump directly, such as login and registration //We can add some conditional judgment, and then jump to the corresponding path //For example, if(){next('/login')} })
be careful
When we go in, the first page title we get is undefined, which is caused by the nesting of routes
When we print to, we find that there is a matched array. The path of matcher[0] is' / home ', and the path of matcher[1] is' / home/news', so we need to change the document title = to. matched[0]. meta. title
Rear hook, guard
router.afterEach((to,from)=>{ })
All of the above are global guards. In addition, there are
- Route exclusive guard
const routes = [ { path:'/user/:userId', component:User, meta:{ title:'user' }, beforeEnter:(to,from,next)=>{ ... next() } }, ... ]
- Guard in component (document use)
keep-alive
-
Note: when we switch components, nothing remains, so every time we switch components, we will call the create function in their life cycle function, that is, every time we create components.
- Therefore, there is a destroyed () periodic function inside our component
-
Keep alive is a built-in component of Vue, which can keep the contained components in the state or avoid re rendering
-
Router view is also a component (defined at the time of new Vue router). If it is directly wrapped in keep alive, all view components matching the path will be cached
<keep-alive> <router-view></router-view> </keep-alive>
Now demand: when you enter the home page, the default is to display the news. First click the home page message, then click the user, and then when you return to the home page, you will see the home page message
This can be solved by using the navigation guard and active state function we mentioned earlier
At home In Vue
<template> <div> <h2>I'm the home page</h2> <p> I am the content of the home page </p> <router-link to="/home/news" tag="button">Journalism</router-link> <router-link to="/home/message" tag="button">news</router-link> <router-view></router-view> </div> </template> <script> export default { name:"Home", data(){ return{ path:'/home/news' } }, created () { console.log("created") }, destroyed () { console.log("destory") }, //The following two functions are valid in the case of keep alive activated () { console.log("HOME The component is active"); this.$router.push(this.path).catch(err=>{}) //Here The reason for catch is to avoid repeated submission of routing console errors through / home/news }, deactivated () { console.log("HOME Component resting in cache") }, beforeRouteLeave(to,from,next){ console.log(this.$route.path); this.path = this.$route.path next(); } } </script>
Note: sometimes we don't want all components in the app to be cached. For example, we want to re create some files. At this time, we have two very important properties
-
include - string or regular expression that takes care of matching components will be cached
-
exclude - string or regular expression. Any matching components will not be cached
-
The string inside is the name attribute of each vue component when exporting
<keep-alive exclude="Profile,User"> <router-view></router-view> </keep-alive>