Vue-Router
Vue-Router是一个插件,需要是用Vue.use()去使用。要求必须要有一个install方法,将来会被调用。
我们当前使用hash模式去实现,当前全部路由表如下:
import Vue from 'vue'
import VueRouter from './kvue-router'
import Home from '../views/Home.vue'
Vue.use(VueRouter)
//VueRouter是一个插件
// 内部做了什么
// 1:实现并声明了两个组件router-view router-link
// 2:install:this.$router.push()
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'),
children: [{
path: '/about/info',
name: 'info',
component: {
render(h) {
return h('div', 'info page')
}
}
}, ]
}
]
const router = new VueRouter({
mode: 'hash',
base: process.env.BASE_URL,
routes
})
export default router
Vue-router插件代码
import View from './krouter-view'
//1.插件
//2.两个组件
//vue插件:
// function object
// 要求必须有一个install方法,将来会被Vue.use调用
let Vue //保存Vue的构造函数,插件中使用
class VueRouter {
constructor(options){
this.$options=options
// 设置初始化页面路由路径
this.current=window.location.hash.slice(1)||'/'
// 设置一个响应式数组,用来记录当前路由所有层级
Vue.util.defineReactive(this,'matched',[])
// 初始化路由表
this.match()
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
// })
}
match(routes){
routes=routes||this.$options.routes
// 下面规则是根据我自己的路由表写的
for(const route of routes){
if(route.path==='/'&&this.current==='/'){
this.matched.push(route)
return
}
// 判断路由地址是否在当前路径内,想路由表内添加祖先路由,递归调用
if(route.path!=='/'&&this.current.indexOf(route.path)!=-1){
this.matched.push(route)
if(route.children){
this.match(route.children)
}
return
}
}
}
onHashChange(){
console.log(window.location.hash.slice(1))
this.current=window.location.hash.slice(1)
this.matched=[]
this.match()
}
}
VueRouter.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,
require:true
}
},
render(h) {
return h('a',{attrs:{href:'#'+this.to}},this.$slots.default)
}
})
Vue.component('router-view',View)
}
export default VueRouter
krouter-view代码
export default {
render(h){
// 标记当前router-view深度
this.$vnode.data.routerView=true
// 记录路由深度
let depth=0
let parent=this.$parent
// 递归遍历父组件记录当前路由深度
while(parent){
const vnodeData=parent.$vnode&&parent.$vnode.data
if(vnodeData){
if(vnodeData.routerView){
depth++
}
}
parent=parent.$parent
}
let component=null
const route=this.$router.matched[depth]
if(route){
component=route.component
}
return h(component)
}
}