Vue router is a plug-in of Vue. It is a front-end routing manager for Vue. It is usually divided intohash
Andhistory
pattern.
- Hash mode
- The # following content in the URL is used as the path address. If only the path address is modified, the browser will not send a request to the server, but will only store the current path in history
- By listening to hashchange events, get the hash changes, and load different components according to the configuration
- History mode
- Through history The pushstate () method changes the address bar. Similarly, it will not send a request to the server, but will only be stored in history
- Listen to the pop state event when we are in history back()、history. Forward (), this event will be triggered when the browser moves forward and backward, and then find different components through configuration to re render
First, we observe the basic information of Vue router from the perspective of use
import Vue from "vue";
import Router from "vue-router";
//Register plug-ins
Vue.use(Router);
//Instantiation
const router = new Router({
mode: "history",
routes: [
{
path: "/",
name: "index",
component: () => import("./views/layout/index.vue");
},
]
})
//Create Vue instance and register router object
new Vue({
router,
render: h => h(App)
}).$mount("#app");
- Register plug-ins
- Instantiate Vue router and initialize configuration
- Create Vue instance and register router object
We can get that Vue router is a class that exposes an install method and is a static method, and the constructor has properties to accept plug-in configuration
Let’s look at the basic properties and methods of Vue router through the source code
Properties:
Options: used to record the objects passed in the constructor
Data: is an object with a current attribute to record the current routing address by calling Vue Observable to achieve its responsive
Routemap: used to record the mapping relationship between routing objects and components
method:
Constructor (options): constructor
Install (Vue): a static method used to register plug-ins
Init(): initialize and call the following methods
Initevent(): register the pop state method to listen for browser address changes
Createroutemap(): initializes Routemap
Initcomponents (Vue): create router link and router view components
Use Vue cli to initialize the project and modify the import address
Implement the install static method
- The plug-in only needs to be installed once
- In order to facilitate Vue router instance method to use Vue method, Vue build function needs to be stored globally
let _Vue = null
export default class VueRouter {
static install (Vue) {
// 1. Determine whether the current plug-in is installed
if (VueRouter.install.installed) {
return
}
VueRouter.install.installed = true
// 2. Record the Vue constructor to a global variable
_Vue = Vue
// 3. Inject the router object passed in when creating the Vue instance into the Vue instance
_Vue.mixin({
beforeCreate () {
If (this. $options. Router) {// execute in Vue. Other components $options.router do not exist. Ensure that the following code is executed once
_Vue.prototype.$router = this.$options.router
}
}
})
}
}
Implement constructor
constructor (options) {
this.options = options
this.data = _Vue.observable({
current: '/'
})
this.routeMap = {}
}
Implement createroutemap
As we just said, the function of createroutemap is to convert the routes routing rules passed in options into key value pairs and store them in Routemap
createRouteMap () {
this.options.routes.forEach(route => {
this.routeMap[route.path] = route.component
})
}
Implement initcomponents
First create the route link component
<router-link to="/">Home</router-link>
To in router link is equivalent to a hyperlink, and the internal content is equivalent to the internal content of a tag
initComponents (Vue) {
Vue.component('router-link', {
props: {
to: String
},
template: '<a :href="to"><slot></slot></a>'
})
}
At this time, we can implement our init method by the way
init () {
this.createRouteMap()
this.initComponents(_Vue)
}
When we call init, we mix in the last in install, and then we get it
let _Vue = null
export default class VueRouter {
constructor (options) {
this.options = options
this.data = _Vue.observable({
current: '/'
})
this.routeMap = {}
}
createRouteMap () {
this.options.routes.forEach(route => {
this.routeMap[route.path] = route.component
})
}
init () {
this.createRouteMap()
this.initComponents(_Vue)
}
initComponents (Vue) {
Vue.component('router-link', {
props: {
to: String
},
template: '<a :href="to"><slot></slot></a>'
})
}
static install (Vue) {
// 1. Determine whether the current plug-in is installed
if (VueRouter.install.installed) {
return
}
VueRouter.install.installed = true
// 2. Record the Vue constructor to a global variable
_Vue = Vue
// 3. Inject the router object passed in when creating the Vue instance into the Vue instance
_Vue.mixin({
beforeCreate () {
If (this. $options. Router) {// execute in Vue. Other components $options.router do not exist. Ensure that the following code is executed once
_Vue.prototype.$router = this.$options.router
this.$options.router.init()
}
}
})
}
}
Then we modify the vuerouter plug-in imported by import, run the project and find

“You are using Vue’s run-time only build, and the template compiler is not available. Either precompile the template as a render function or use a build that contains a compiler.”
This problem is related to the differences in the build versions of Vue.
When we use cli to run the project, we use the runtime version of Vue. It does not support template compilation. It needs to be compiled in advance when packaging. The full version includes the runtime version and compiler. When running, the template will be converted into render function, so the volume is about 10KB larger than the runtime version.
In view of this situation, Vue officials have given our solution(Reference link), just need us in Vue config. JS, set runtimecompiler to true.
In addition, we can also use the render rendering template ourselves.
initComponents (Vue) {
Vue.component('router-link', {
props: {
to: String
},
// template: '<a :href="to"><slot></slot></a>'
Render (H) {// h is a function used to create a virtual dom
return h('a', {
attrs: {
href: this. To // history mode
}
}, [this.$slots.default])
}
})
}
Continue to create the route view component
The content of our route view component has been stored in the Routemap, so we only need to take it out and convert it into vdom
initComponents (Vue) {
Vue.component('router-link', {
props: {
to: String
},
// template: '<a :href="to"><slot></slot></a>'
Render (H) {// h is a function used to create a virtual dom
return h('a', {
attrs: {
href: this. To // history mode
}
}, [this.$slots.default])
}
})
const _ This = this // record the current vuerouter object
Vue.component('router-view', {
render (h) {
const component = _this.routeMap[_this.data.current]
return h(component)
}
})
}
At this time, when we thought that the basic functions of our Vue router had been completed, it suddenly occurred to us that we had ignored one thing, because the default event of the a tag used by our previous route link was to jump and request from the server. Therefore, we need to transform the route link.
initComponents (Vue) {
Vue.component('router-link', {
props: {
to: String
},
// template: '<a :href="to"><slot></slot></a>'
Render (H) {// h is a function used to create a virtual dom
return h('a', {
attrs: {
href: this. To // history mode
},
on: {
click: this.clickHandler
}
}, [this.$slots.default])
},
methods: {
clickHandler (e) {
history. Pushstate ({/ * passed to the population parameter * /}, '', this. To) // change the address bar
this.$ router. data. current = this. To // change current and restart rendering
e.preventDefault()
}
}
})
const _ This = this // record the current vuerouter object
Vue.component('router-view', {
render (h) {
const component = _this.routeMap[_this.data.current]
return h(component)
}
})
}
Up to now, our basic functions have been used, but we found that the initevent mentioned before has not been implemented. Its function is to register the pop state method and monitor the browser address changes. When we click forward and backward, we will find that the page has not changed. Therefore, we also need to implement initevent.
initEvent () {
window. Addeventlistener ('popup ', () = > {// the arrow function does not change the direction of this
this.data.current = window.location.pathname
})
}
Now that we’ve perfected our code, here you are
let _Vue = null
export default class VueRouter {
constructor (options) {
this.options = options
this.data = _Vue.observable({
current: '/'
})
this.routeMap = {}
}
createRouteMap () {
this.options.routes.forEach(route => {
this.routeMap[route.path] = route.component
})
}
init () {
this.createRouteMap()
this.initComponents(_Vue)
this.initEvent()
}
initComponents (Vue) {
Vue.component('router-link', {
props: {
to: String
},
// template: '<a :href="to"><slot></slot></a>'
Render (H) {// h is a function used to create a virtual dom
return h('a', {
attrs: {
href: this. To // history mode
},
on: {
click: this.clickHandler
}
}, [this.$slots.default])
},
methods: {
clickHandler (e) {
history. Pushstate ({/ * passed to the population parameter * /}, '', this. To) // change the address bar
this.$ router. data. current = this. To // change current and restart rendering
e.preventDefault()
}
}
})
const _ This = this // record the current vuerouter object
Vue.component('router-view', {
render (h) {
const component = _this.routeMap[_this.data.current]
return h(component)
}
})
}
initEvent () {
window. Addeventlistener ('popup ', () = > {// the arrow function does not change the direction of this
this.data.current = window.location.pathname
})
}
static install (Vue) {
// 1. Determine whether the current plug-in is installed
if (VueRouter.install.installed) {
return
}
VueRouter.install.installed = true
// 2. Record the Vue constructor to a global variable
_Vue = Vue
// 3. Inject the router object passed in when creating the Vue instance into the Vue instance
_Vue.mixin({
beforeCreate () {
If (this. $options. Router) {// execute in Vue. Other components $options.router do not exist. Ensure that the following code is executed once
_Vue.prototype.$router = this.$options.router
this.$options.router.init()
}
}
})
}
}
function! Available! Normal!
The history mode of Vue router is completed!