vue-router总结

188 阅读2分钟

一 使用

  1. 下载npm install vue-router --save

  2. 在项目中新建文件夹 router/index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
/*引入pages*/
const MSite = ()=>import('../pages/MSite/MSite');
const Profile = ()=>import('../pages/Profile/profile');

//申明使用插件
Vue.use(VueRouter)
export default new VueRouter({
  routes:[
    {
      path:'/msite',
      component: MSite,
      meta: {
        showFooter: true
      }
    },
    {
      path:'/profile',
      component:Profile,
      meta: {
        showFooter: true
      }
    }
    {
      path: '/',
      redirect: '/msite' //系统默认页
    }
  ]
})
  1. 在main.js中全局使用router
import Vue from 'vue'
import App from './App'
import router from './router' //引入路由

new Vue({
  el: '#app',
  components: { App },
  template: '<App/>',
  router  //引入路由
})
  1. 在页面中的使用
<template>
  <div class="hello">
     <router-link to="/">网站首页</router-link>
     <router-view></router-view>
  </div>
</template>

二 原理

2.1 index.js文件改写和说明

下方文件可以看出vue-route是用的new,说明./vue-router文件中是一个构造函数或者类,传入的参数是一个对象。

import Vue from 'vue'
import VueRouter from './vue-router'
import Home from '../views/Home.vue'
Vue.use(VueRouter)
const routes =[
	{
		path:'/',
		name:'home',
		component:Home
	},
	{
		path:'/about',
		name:'about',
		component: () => import('../views/About.vue')
	}
]
const router=new VueRouter({
	mode:'history',
	base:process.env.BASE_URL,
	routes
})
export default router

2.2kvue-router.js文件说明

​ 首先声明一个全局变量let vue,这是一个插件,在加入vue中都会执行install方法,并且将vue传入。我们用 Vue=_Vue;将前方声明的全局变量赋值为vue。接下来通过混入的方法将所有的组件种豆混入生命周期函数beforeCreate和原有的合并,判断在根实例后挂载。让后全局注册两个组件。

​ 声明了一个类KVueRouter,类在new的时候会执行constructor函数,constructor函数首先将传入的参数保存,接着通过vue源码中的util.defineReactive将current做响应式,current变化就会刷新页面,接着给window绑定hashchange和load事件。执行onHashChange函数,函数内会将最新的值赋值给current。

​ 将参数route数组进行处理,处理为一个对象,对象中的key为route.path,值为route(数组的每一项)

当URL的片段标识符更改时,将触发hashchange事件

load事件 就是窗体加载事件 应对不在首页点击刷新。

import Link from './router-link'
import View from './router-view'
let Vue;
class KVueRouter{
	constructor(options){
		this.$options=options
		// 需要创建响应式的current属性
	    // 利用Vue提供的defineReactive做响应化
	    // 这样将来current变化的时候,依赖的组件会重新render
	    Vue.util.defineReactive(this,'current','/')
	    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)
	}
}
KVueRouter.install=function(_Vue){
	Vue=_Vue;
	Vue.mixin({
		//混入所有的组件执行该生命周期时都会执行下面的事件
		beforeCreate(){
			if(this.$options.router){
				//this指向vue实力确保是根实例让后挂载。
				Vue.prototype.$router=this.$options.router
			}
		}
	})
	//全局注册组件
	Vue.component('router-link',Link)
	Vue.component('router-view',View)

}
export default KVueRouter

2.3router-link文件说明

router-link组件的内容,将router-link标签转换为a标签。

export default{
	props:{
		to:{
			type:String,
			required:true
		}
	},
	render(h){
		// <a href="#/about">abc</a>
	    // <router-link to="/about">xxx</router-link>
	    // h(tag, data, children)
	    //console.log(this.$slots);
	    return h('a', { attrs: { href: '#' + this.to } }, this.$slots.default)
	    // return <a href={'#' + this.to}>{this.$slots.default}</a>
	}
}

2.4router-view文件说明

route-view组件的内容,将route-view标签改为和路由对应的组件

export default{
	render(h){
		const {routeMap,current}=this.$router;
		const component = routeMap[current].compont || null;
		return h(compont)
	}
}