1. The analysis
There are two common Vue Router modes: Hash mode and history mode. Here is an attempt to wrap a simple Vue Router in hash mode.
- Hash mode: use the anchor after url# to distinguish components. When the hash changes, the page is not reloaded, only the onhashchange event is triggered
- History mode: This mode takes advantage of the new pushState() and replaceState() methods in the HTML5 History Interface. These two methods apply to the browser record stack and provide the ability to modify the history in addition to the existing back, Forward, and Go methods. It’s just that when they make changes that change the current URL, the browser doesn’t immediately send requests to the back end.
2. Implement
let Vue
class Router {
static install(_Vue) {
Vue = _Vue
Vue.mixin({
beforeCreate() {
if(this.$options.router) {
Vue.prototype.$flyRouter = this.$options.router
this.$options.router.init()
}
}
})
}
constructor(options) {
this.$options = options
this.routeMaps = {}
this.app = new Vue({
data: {
currentUrl: '/'}})}init() {
this.bindEvents()
this.generateHashMap()
this.createComponent(Vue)
}
bindEvents() {
window.addEventListener('hashchange', this.hashChangeEvent.bind(this), false)
window.addEventListener('load', this.hashChangeEvent.bind(this), false)}hashChangeEvent(e) {
let hash = this.getHash()
let { from, to } = this.getFrom(e)
let router = this.routeMaps[hash]
if(router.beforeEnter) {
router.beforeEnter(to, from, () => {
this.app.currentUrl = hash})}else {
this.app.currentUrl = hash
}
}
getFrom(e) {
let from = e.oldURL || ' '
let to = e.newURL || '/'
return {
from,
to
}
}
getHash() {
return window.location.hash.substr(1) || '/'
}
push(url) {
window.location.hash = url
}
generateHashMap() {
this.$options.routes.forEach(item => {
this.routeMaps[item.path] = item.component
})
}
createComponent(Vue) {
const that = this
Vue.component('router-link',{
render(h) {
return h('a', {
attrs: {
href: The '#' + this.to
}
},
[this.$slots.default]
)
},
props: {
to: String
}
})
Vue.component('router-view', {
render(h) {
let component = that.routeMaps[that.app.currentUrl]
return h(component)
}
})
}
}
export default Router
Copy the code
3. The application of
Reference custom router.js in router/index.js
import Vue from 'vue'
import Router from '@/utils/router'
import Home from '@/pages/Home.vue'
import About from '@/pages/About.vue'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
component: Home
},
{
path: '/about',
component: About,
beforeEnter: (to,from,next) => {
console.log('output',to,from)
setTimeout(() => {
next()
}, 3000)
}
}
]
})
Copy the code
The code in app.vue
<template>
<div id="app">
<router-link to="/about"> Go to the About page </router-link> <router-link to="/"</router-link> <router-view></router-view> </div> </template>Copy the code
The code in main.js
import Vue from 'vue'
import App from './App'
import router from '@/router'
Vue.config.productionTip = false
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
Copy the code
4. To summarize
As can be seen from the above code, the custom router has basically realized the functions of a Vue Router, and its usage is the same as that of a Vue Router.