popstate
When the browser moves forward or backward, it triggers a POPState event and listens for the popState event to display the corresponding component based on the address.
The VueRouter class contains properties and methods
Vue-router can be called to analyze the attributes and methods it contains.
// router.js
import Vue from 'vue'
import VueRouter from '.. /vueroute/index.js'
import Home from '.. /views/Home.vue'
Vue.use(VueRouter)
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')}]const router = new VueRouter({
mode: 'history'.base: process.env.BASE_URL,
routes
})
export default router
Copy the code
// mian.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
new Vue({
router,
render: h= > h(App)
}).$mount('#app')
Copy the code
From the above call, you can see that the VueRouter class needs the following properties and methods
VueRouter
attribute | type | use |
---|---|---|
options | Object | Used to save the options object passed in when VueRouter was initialized |
data.current | String | Reactive data for storing the routing address of the current page |
routeMap | Object | It is used to store incoming routing rules. The key name is the routing address, and the key value is the corresponding component |
methods | use |
---|---|
install | Static method that implements the VUE plug-in mechanism to register the VueRouter to the VUE |
init | Centralize the calls to the various initialization methods |
initRouteMap | Initialize the routeMap object |
initComponents | Initialize the routerLink and routerView components |
initEvents | Initialize listening for popState events |
Implementation of the install method
let _Vue = null;
export default class VueRouter {
static install (Vue) {
// 1. Check whether the plug-in is installed
if (VueRouter.install.installed) return
VueRouter.install.installed = true;
// 2. Record the Vue constructor as a global variable, so that later methods can use Vue
_Vue = Vue;
// 3. Inject the router object passed into the Vue instance
// Blend in to get the Vue instance, i.e. this refers to the unvue instance
_Vue.mixin({
beforeCreate () {
if (this.$options.router) { // Mount only needs to be called once
// Mount the routing object to the prototype chain of the Vue instance
_Vue.prototype.$router = this.$options.router
// Call the initialization method of the route object
this.$options.router.init()
}
}
})
}
}
Copy the code
Constructor initialization
constructor (options) {
this.options = options // Stored routing rules
this.routeMap = {} // The routing address corresponds to the component. The key name is the routing address, and the key value is the corresponding component
// Use the Vue observable to implement responsiveness
this.data = _Vue.observable({
current: '/'})}Copy the code
An implementation of the initRouteMap method
// Initialize the routeMap
initRouteMap () {
// Iterate through all the routing rules, parsing the routing rules into key-value pairs, and storing them in the routeMap
this.options.routes.forEach(route= > {
this.routeMap[route.path] = route.component
})
}
Copy the code
The implementation of the initComponents method
// Initialize the component
initComponents (Vue) {
const _self = this
// Implement the router-link component
Vue.component('router-link', {
props: {
to: String // It is used to accept the route address to jump to
},
render (h) {
return h ('a', {
attrs: {
href: this.to
},
on: {
click: this.clickHandler
}
}, [this.$slots.default])
},
methods: {
clickHandler (e) {
// Change the browser address bar
history.pushState({}, ' '.this.to)
// Update the current address of the storage
_self.data.current = this.to
// prevent a tag from jumping by defaulte.preventDefault(); }}})// Implement the router-view component
Vue.component('router-view', {
render (h) {
// Find the corresponding component based on the current address
const component = _self.routeMap[_self.data.current]
// Use vue's render function to render the component
return h(component)
}
})
}
Copy the code
Implementation of the initEvents method
// Initialize the event
initEvents () {
// Create a listener event
window.addEventListener('popstate'.(event) = > {
// Update the current routing address
this.data.current = window.location.pathname
});
}
Copy the code
The implementation of the init method
init () {
// Initialize the routeMap object
this.initRouteMap()
// Create router-link and router-view components
this.initComponents(_Vue)
// Initialize listening for popState events
this.initEvents()
}
Copy the code
All code for the VueRouter class
let _Vue = null;
export default class VueRouter {
static install (Vue) {
// 1. Check whether the plug-in is installed
if (VueRouter.install.installed) return
VueRouter.install.installed = true;
// 2. Record the Vue constructor as a global variable, so that later methods can use Vue
_Vue = Vue;
// 3. Inject the router object passed into the Vue instance
// Blend in to get the Vue instance, i.e. this refers to the unvue instance
_Vue.mixin({
beforeCreate () {
if (this.$options.router) { // Mount only needs to be called once
// Mount the routing object to the prototype chain of the Vue instance
_Vue.prototype.$router = this.$options.router
// Call the initialization method of the route object
this.$options.router.init()
}
}
})
}
constructor (options) {
this.options = options // Stored routing rules
this.routeMap = {} // The routing address corresponds to the component. The key name is the routing address, and the key value is the corresponding component
// Use the Vue observable to implement responsiveness
this.data = _Vue.observable({
current: '/'
})
}
init () {
// Initialize the routeMap object
this.initRouteMap()
// Create router-link and router-view components
this.initComponents(_Vue)
// Initialize listening for popState events
this.initEvents()
}
// Initialize the routeMap
initRouteMap () {
// Iterate through all the routing rules, parsing the routing rules into key-value pairs, and storing them in the routeMap
this.options.routes.forEach(route= > {
this.routeMap[route.path] = route.component
})
}
// Initialize the component
initComponents (Vue) {
const _self = this
// Implement the router-link component
Vue.component('router-link', {
props: {
to: String // It is used to accept the route address to jump to
},
render (h) {
return h ('a', {
attrs: {
href: this.to
},
on: {
click: this.clickHandler
}
}, [this.$slots.default])
},
methods: {
clickHandler (e) {
// Change the browser address bar
history.pushState({}, ' '.this.to)
// Update the current address of the storage
_self.data.current = this.to
// prevent a tag from jumping by defaulte.preventDefault(); }}})// Implement the router-view component
Vue.component('router-view', {
render (h) {
// Find the corresponding component based on the current address
const component = _self.routeMap[_self.data.current]
// Use vue's render function to render the component
return h(component)
}
})
}
// Initialize the event
initEvents () {
// Create a listener event
window.addEventListener('popstate'.(event) = > {
// Update the current routing address
this.data.current = window.location.pathname }); }}Copy the code
conclusion
In order to analyze the principle, only the simplest version of VueRouter is implemented. The To attribute of the routerLink component only supports String parameters. You can modify it to match the object type