一、需求分析
- 作为一个插件存在:需要实现vueRouter类及install方法;
- 实现两个全局组件: router-link用于路由跳转,router-view用于展示组件内容;
- 监控url变化:监听hashchange事件和load事件;
- 展示对应url内容: 创建一个响应值,当它改变时,展示对应的组件内容。
二、准备工作
- 创建一个vue项目,安装vue-router
- 改造router/index.js文件,增加一个路由,用于跳转,如下
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
{
path: '/Home',
name: 'Home',
component: Home
}
]
})
- 在components文件里实现创建Home组件
- 修改App.vue文件,增加下面代码块,用于路由跳转
<div id="nav">
<router-link to="/">HelloWorld</router-link>
<router-link to="/Home">Home</router-link>
</div>
- 在router文件夹的同一级创建xRouter,复制router/index.js到XRouter文件夹里,把main.js里引用router改为xRouter;
import router from './xRouter'
- 把xRouter/index.js里引用vue-router改为xvue-router
import Router from './xvue-router'
- xRouter文件夹里创建xvue-router.js文件
三、实现
1、创建vueRouter类及install方法
- 在xvue-router.js里创建XVueRouter类,并且导出;同时定义install方法,大致结构如下
class XVueRouter {
constructor(options) {}
}
XVueRouter.install = function(){}
export default XVueRouter
- 保存传入参数
constructor(options) {
this.$options = options
}
- 实现install方法,注册$router,使用mixins来获得项目的router内容,代码如下:(官方vue插件规范:Vue.js 的插件应该暴露一个 install 方法。这个方法的第一个参数是 Vue 构造器,第二个参数是一个可选的选项对象)
XVueRouter.install = function(_Vue){
Vue = _Vue; //保存Vue
Vue.mixin({
beforeCreate() {
if(this.$options.router) {
Vue.prototype.$router = this.$options.router
}
}
})
}
使用mixin而不直接在构造函数里获取router数据的原因是,在main.js里new Vue()时,才会把router实例传进来,但是,在router/index.js的时候,就已经调用了Vue.use(),也就是会执行install方法,执行了之后才会创建router实例,所以,在执行install方法的时候,router实例还没创建,也就无法获得router数据了。
- 实现router-link和router-view,代码如下
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',{
render(h) {
const { hashMap, currentUrl } = this.$router
return h(hashMap[currentUrl].component)
}
})
- XVueRouter代码如下
class XVueRouter {
constructor(options) {
this.$options = options
//定义一个响应式的变量来存当前url 参数:(object,key,value)
Vue.util.defineReactive(this,'currentUrl','/')
//创建一个hashMap表,存对应的路由及组件
this.hashMap = {};
this.$options.routes.forEach(item => {
this.hashMap[item.path] = item
})
//监听url的变化
window.addEventListener('hashchange',this.changeCurrentUrl.bind(this));
window.addEventListener('load',this.changeCurrentUrl.bind(this));
}
changeCurrentUrl() {
this.currentUrl = window.location.hash.slice(1)
}
}
到此,就基本实现了路由跳转。