一、先用vue-router实现一个简单的路由示例
1、安装vue-router
npm install vue-router --save
2、创建router文件夹,在文件夹下新建index.js文件
import Vue from "vue";
import VueRouter from "vue-router";
import Home from "../components/Home.vue";
import About from "../components/About.vue";
Vue.use(VueRouter)
const routes = [{
path: '/',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
component: About
}
]
//创建VueRouter实例
const router = new VueRouter({
mode: 'history',
routes
})
export default router
3、在根组件上添加实例
import router from "./router";
new Vue({
router,
render: h => h(App),
}).$mount('#app')
4、在app.vue里引用router-link
<router-link to="/">Home</router-link>
<router-link to="/about">About</router-link>
<router-view></router-view>
5、创建Home和About组件并启动服务
二、实现简版的KVueRouter
1、新建krouter文件夹,并将router下的js复制到当前文件夹下,修改如下代码
import Vue from "vue";
//引用将要实现的KVueRouter
import KVueRouter from "./kvue-router";
import Home from "../components/Home.vue";
import About from "../components/About.vue";
//安装插件
Vue.use(KVueRouter)
let routes = [{
path: '/',
component: Home
}, {
path: '/about',
component: About
}];
//KVueRouter实例
const router = new KVueRouter({
mode: 'history',
routes
})
export default router
2、修改main.js
//在根组件上添加实例KVueRouter
import router from "./krouter";
new Vue({
router,
render: h => h(App),
}).$mount('#app')
3、在krouter下新建kvue-router.js,实现KVueRouter类和install方法
//引用构造函数,KVueRouter中要使用
let Vue;
//KVueRouter类
class KVueRouter {
constructor(options) {
this.$options = options
}
}
KVueRouter.install = function (_Vue) {
//引用构造函数,KVueRouter中要使用
Vue = _Vue;
// 全局混入, 将$router放到Vue.prototype上,
// 因为main.js是这样引用的
// new Vue({
// router,
// render: h => h(App),
// }).$mount('#app')
Vue.mixin({
beforeCreate() {
//只有根组件才有trouter
if (this.$options.router) {
Vue.prototype.$router = this.$options.router
}
}
})}
export default KVueRouter
4、在install方法下创建router-link组件和router-view组件(也可以放在单独的js中然后引用)
Vue.component('router-link', {
//传入to属性 <router-link to="/">Home</router-link>
props: {
to: {
type: String,
required: true
}
},
render(h) {
//h(tag,data,children)
//渲染成a标签,并指定href属性
//this.$slots.default 通过匿名插槽的方式,取到
//<router-link to="/">Home</router-link>中的Home
return h('a', {
attrs: {
href: '#' + this.to
}
}, this.$slots.default)
}
})
Vue.component('router-view', {
render(h) {
//暂时不渲染
return h(null);
}
});
5、监控url变化,定义响应式的current属性,监听onHashChange事件
class KVueRouter {
constructor(options) {
this.$options = options
const initial = window.location.hash.slice(1) || '/'
//current应该是响应式的
Vue.util.defineReactive(this, 'current', initial)
//监听url的hash变化
window.addEventListener('hashchange', this.onHashChange.bind(this))
window.addEventListener('load', this.onHashChange.bind(this))
this.routeMap = {};
options.routes.forEach(route => {
this.routeMap[route.path] = route.component
})
}
onHashChange() {
this.current = window.location.hash.slice(1)
}
}
6、创建路由表映射,供router-view组件使用
this.routeMap = {};
options.routes.forEach(route => {
this.routeMap[route.path] = route
})
7、渲染router-view组件
Vue.component('router-view', {
render(h) {
const {
routeMap,
current
} = this.$router;
let component = routeMap[current].component || null;
return h(component);
}
});
三、贴上全部代码
1、kvue-router
let Vue;
class KVueRouter {
constructor(options) {
this.$options = options
const initial = window.location.hash.slice(1) || '/'
//current应该是响应式的
Vue.util.defineReactive(this, 'current', initial)
window.addEventListener('hashchange', this.onHashChange.bind(this))
window.addEventListener('load', this.onHashChange.bind(this))
this.routeMap = {};
options.routes.forEach(route => {
this.routeMap[route.path] = route
})
}
onHashChange() {
this.current = window.location.hash.slice(1)
console.log(this.current);
}
}
KVueRouter.install = function (_Vue) {
Vue = _Vue;
Vue.mixin({
beforeCreate() {
if (this.$options.router) {
Vue.prototype.$router = this.$options.router
}
}
})
Vue.component('router-link', {
props: {
to: {
type: String,
required: true
}
},
render(h) {
//h(tag,data,children)
return h('a', {
attrs: {
href: '#' + this.to
}
}, this.$slots.default)
}
})
Vue.component('router-view', {
render(h) {
const {
routeMap,
current
} = this.$router;
let m = routeMap[current].component || null;
return h(m);
}
});
}
export default KVueRouter
2、index.js
import Vue from "vue";
import KVueRouter from "./kvue-router";
import Home from "../components/Home.vue";
import About from "../components/About.vue";
Vue.use(KVueRouter)
let routes = [{
path: '/',
component: Home
}, {
path: '/about',
component: About
}];
const router = new KVueRouter({
mode: 'history',
routes
})
export default router
3、main.js
import Vue from 'vue'
import App from './App.vue'
import router from "./krouter";
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App),
}).$mount('#app')
4、app.vue
<template>
<div id="app">
<router-link to="/">Home</router-link>
<router-link to="/about">About</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {};
</script>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>