1.手写vue-router源码
let Vue = null
class HistoryRoute {
constructor() {
this.current = null
}
}
class VueRouter {
constructor(options) {
this.mode = options.mode || 'hash'
this.routes = options.routes || []
this.routesMap = this.createMap(this.routes)
this.history = new HistoryRoute()
this.init()
}
createMap(routes) {
return routes.reduce((pre, current) => {
pre[current.path] = current.component
return pre
}, {})
}
init() {
if (this.mode === 'hash') {
location.hash ? "" : (location.hash = '/')
const handleRouter = () => {
this.history.current = location.hash.slice(1)
}
window.addEventListener('load', handleRouter)
window.addEventListener('hashchange', handleRouter)
}
else {
location.pathname ? "" : (location.pathname = '/')
const handleRouter = () => {
this.history.current = location.pathname
}
window.addEventListener('load', handleRouter)
window.addEventListener('popstate', handleRouter)
}
}
}
VueRouter.install = function (v) {
Vue = v
Vue.mixin({
beforeCreate() {
if (this.$options && this.$options.router) {
this._root = this
this._router = this.$options.router
Vue.util.defineReactive(this, 'vuerouter', this._router.history)
}
else {
this._root = this.$parent && this.$parent._root
}
Object.defineProperty(this, '$router', {
get() {
return this._root._router
}
})
Object.defineProperty(this, '$route', {
get() {
return this._root._router.history.current
}
})
}
})
Vue.component('router-link', {
props: {
to: String
},
render(h) {
const mode = this._self._root._router.mode
const to = mode === 'hash' ? '#' + this.to : this.to
return h('a', {
attrs: { href: '' }, on: {
click: (e) => {
e.preventDefault()
window.history.pushState(null, null, to)
const eventKey = mode == 'hash' ? 'hashchange' : 'popstate'
const event = new Event(eventKey);
window.dispatchEvent(event);
}
}
}, this.$slots.default)
}
})
Vue.component('router-view', {
render(h) {
console.log('this', this);
const current = this._self._root._router.history.current
const comp = this._self._root._router.routesMap[current]
return h(comp)
}
})
}
export default VueRouter
2.使用
import VueRouter from './core'
import Vue from "vue";
import HomeVue from '../view/home-vue.vue'
import AboutVue from '../view/about-vue.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/home',
component: HomeVue
},
{
path: '/about',
component: AboutVue
}
]
const router = new VueRouter({
mode: 'history',
routes,
})
export default router
<template>
<div id="app">
<router-link to="/home">home</router-link>
<router-link to="/about">about</router-link>
<router-view></router-view>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
},
beforeCreate() {
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
margin-top: 60px;
}
</style>
3.页面效果
