文章目录
- 分步骤实现
- 创建 VueRouter 类
- 创建静态方法,实现 install
- 实现构造函数
- 实现 createRouteMap
- 实现 initComponents 方法 - router-link
- 实现 initComponents 方法 - router-view
- 实现 initEvents
- 完整代码
分步骤实现
创建 VueRouter 类
/**
* VueRouter Class
* -------------------------------------
* + options
* + data
* + routeMap
* -------------------------------------
* + Constructor(Option): VueRouter
* _install(Vue): void
* + init(): void
* + initEvent: void
* + CreateRouteMap(): void
* + initComponents(Vue): void
*/
export default class VueRouter{
}
创建静态方法,实现 install
/**
* VueRouter Class
* -------------------------------------
* + options
* + data
* + routeMap
* -------------------------------------
* + Constructor(Option): VueRouter
* _install(Vue): void
* + init(): void
* + initEvent: void
* + CreateRouteMap(): void
* + initComponents(Vue): void
*/
export default class VueRouter{
static install(Vue){
// 1.判断当前插件是否被安装
if(VueRouter.install.installed){
return
}
VueRouter.install.installed = true
// 2.把 Vue 构造函数记录到全局变量
_Vue = Vue
// 3.把创建 Vue 实例的时候传入的 router 对象注入到 Vue 实例上
// 混入
_Vue.mixin({
beforeCreate(){
// router 执行,组件不执行
if(this.$options.router){
_Vue.prototype.$router = this.$options.router
}
}
})
}
}
实现构造函数
/**
* VueRouter Class
* -------------------------------------
* + options
* + data
* + routeMap
* -------------------------------------
* + Constructor(Option): VueRouter
* _install(Vue): void
* + init(): void
* + initEvent: void
* + CreateRouteMap(): void
* + initComponents(Vue): void
*/
export default class VueRouter{
static install(Vue){
// 1.判断当前插件是否被安装
if(VueRouter.install.installed){
return
}
VueRouter.install.installed = true
// 2.把 Vue 构造函数记录到全局变量
_Vue = Vue
// 3.把创建 Vue 实例的时候传入的 router 对象注入到 Vue 实例上
// 混入
_Vue.mixin({
beforeCreate(){
// router 执行,组件不执行
if(this.$options.router){
_Vue.prototype.$router = this.$options.router
}
}
})
}
constructor(options){
this.options = options
this.routeMap = {}
// 将 current 注册为响应式对象
this.data = _Vue.observable({
current: '/'
})
}
}
实现 createRouteMap
/**
* VueRouter Class
* -------------------------------------
* + options
* + data
* + routeMap
* -------------------------------------
* + Constructor(Option): VueRouter
* _install(Vue): void
* + init(): void
* + initEvent: void
* + CreateRouteMap(): void
* + initComponents(Vue): void
*/
export default class VueRouter{
static install(Vue){
// 1.判断当前插件是否被安装
if(VueRouter.install.installed){
return
}
VueRouter.install.installed = true
// 2.把 Vue 构造函数记录到全局变量
_Vue = Vue
// 3.把创建 Vue 实例的时候传入的 router 对象注入到 Vue 实例上
// 混入
_Vue.mixin({
beforeCreate(){
// router 执行,组件不执行
if(this.$options.router){
_Vue.prototype.$router = this.$options.router
}
}
})
}
constructor(options){
this.options = options
this.routeMap = {}
// 将 current 注册为响应式对象
this.data = _Vue.observable({
current: '/'
})
}
createRouteMap(){
// 遍历所有的路由规则,把路由规则解析成键值对的形式 存储到 routeMap 中
this.options.routes.forEach(route=>{
this.routeMap[route.path] = route.component
})
}
}
实现 initComponents 方法 - router-link
/**
* VueRouter Class
* -------------------------------------
* + options
* + data
* + routeMap
* -------------------------------------
* + Constructor(Option): VueRouter
* _install(Vue): void
* + init(): void
* + initEvent: void
* + CreateRouteMap(): void
* + initComponents(Vue): void
*/
export default class VueRouter{
static install(Vue){
// 1.判断当前插件是否被安装
if(VueRouter.install.installed){
return
}
VueRouter.install.installed = true
// 2.把 Vue 构造函数记录到全局变量
_Vue = Vue
// 3.把创建 Vue 实例的时候传入的 router 对象注入到 Vue 实例上
// 混入
_Vue.mixin({
beforeCreate(){
// router 执行,组件不执行
if(this.$options.router){
_Vue.prototype.$router = this.$options.router
this.$options.router.init()
}
}
})
}
constructor(options){
this.options = options
this.routeMap = {}
// 将 current 注册为响应式对象
this.data = _Vue.observable({
current: '/'
})
}
init(){
this.createRouteMap()
this.initComponents(_Vue)
}
createRouteMap(){
// 遍历所有的路由规则,把路由规则解析成键值对的形式 存储到 routeMap 中
this.options.routes.forEach(route=>{
this.routeMap[route.path] = route.component
})
}
initComponents(Vue){
const self = this
Vue.component('route-link', {
props: {
to: String
},
template: '<a :href="to"><slot></slot></a>'
})
}
}
遇到问题:you are using the runtime-only build of Vue where the template compiler is not avriable. ...
还有一个 router-view 的报错先不用管,是没定义 router-view 组件
Vue的构建版本:
两种方式:
1、修改配置,新增 vue.config.js 配置文件,修改 runtimeCompiler: true
2、将 template 换成 render
更改为 render 函数
/**
* VueRouter Class
* -------------------------------------
* + options
* + data
* + routeMap
* -------------------------------------
* + Constructor(Option): VueRouter
* _install(Vue): void
* + init(): void
* + initEvent: void
* + CreateRouteMap(): void
* + initComponents(Vue): void
*/
export default class VueRouter{
static install(Vue){
// 1.判断当前插件是否被安装
if(VueRouter.install.installed){
return
}
VueRouter.install.installed = true
// 2.把 Vue 构造函数记录到全局变量
_Vue = Vue
// 3.把创建 Vue 实例的时候传入的 router 对象注入到 Vue 实例上
// 混入
_Vue.mixin({
beforeCreate(){
// router 执行,组件不执行
if(this.$options.router){
_Vue.prototype.$router = this.$options.router
this.$options.router.init()
}
}
})
}
constructor(options){
this.options = options
this.routeMap = {}
// 将 current 注册为响应式对象
this.data = _Vue.observable({
current: '/'
})
}
init(){
this.createRouteMap()
this.initComponents(_Vue)
}
createRouteMap(){
// 遍历所有的路由规则,把路由规则解析成键值对的形式 存储到 routeMap 中
this.options.routes.forEach(route=>{
this.routeMap[route.path] = route.component
})
}
initComponents(Vue){
const self = this
Vue.component('route-link', {
props: {
to: String
},
render(h){
return h('a', {
attrs: {
href: this.to
},
}, [this.$slots.default])
},
// template: '<a :href="to"><slot></slot></a>'
})
}
}
实现 initComponents 方法 - router-view
/**
* VueRouter Class
* -------------------------------------
* + options
* + data
* + routeMap
* -------------------------------------
* + Constructor(Option): VueRouter
* _install(Vue): void
* + init(): void
* + initEvent: void
* + CreateRouteMap(): void
* + initComponents(Vue): void
*/
export default class VueRouter{
static install(Vue){
// 1.判断当前插件是否被安装
if(VueRouter.install.installed){
return
}
VueRouter.install.installed = true
// 2.把 Vue 构造函数记录到全局变量
_Vue = Vue
// 3.把创建 Vue 实例的时候传入的 router 对象注入到 Vue 实例上
// 混入
_Vue.mixin({
beforeCreate(){
// router 执行,组件不执行
if(this.$options.router){
_Vue.prototype.$router = this.$options.router
this.$options.router.init()
}
}
})
}
constructor(options){
this.options = options
this.routeMap = {}
// 将 current 注册为响应式对象
this.data = _Vue.observable({
current: '/'
})
}
init(){
this.createRouteMap()
this.initComponents(_Vue)
}
createRouteMap(){
// 遍历所有的路由规则,把路由规则解析成键值对的形式 存储到 routeMap 中
this.options.routes.forEach(route=>{
this.routeMap[route.path] = route.component
})
}
initComponents(Vue){
const self = this
Vue.component('route-link', {
props: {
to: String
},
render(h){
return h('a', {
attrs: {
href: this.to
},
on: {
click: this.clickHandler
}
}, [this.$slots.default])
},
methods: {
clickHandler(e){
// 取消默认行为
e.preventDefault()
// pushState 改变地址栏,但是不向服务器发送请求
history.pushState({}, '', this.to)
// 当前路径记录到 current 里边
this.$router.data.current = this.to
}
}
// template: '<a :href="to"><slot></slot></a>'
})
Vue.component('router-view',{
// 由于 current 是响应式的,所以这里会自动渲染对应的组件
render(h){
const component = self.routeMap[self.data.current]
return h(component)
}
})
}
}
实现 initEvents
/**
* VueRouter Class
* -------------------------------------
* + options
* + data
* + routeMap
* -------------------------------------
* + Constructor(Option): VueRouter
* _install(Vue): void
* + init(): void
* + initEvent: void
* + CreateRouteMap(): void
* + initComponents(Vue): void
*/
export default class VueRouter{
static install(Vue){
// 1.判断当前插件是否被安装
if(VueRouter.install.installed){
return
}
VueRouter.install.installed = true
// 2.把 Vue 构造函数记录到全局变量
_Vue = Vue
// 3.把创建 Vue 实例的时候传入的 router 对象注入到 Vue 实例上
// 混入
_Vue.mixin({
beforeCreate(){
// router 执行,组件不执行
if(this.$options.router){
_Vue.prototype.$router = this.$options.router
this.$options.router.init()
}
}
})
}
constructor(options){
this.options = options
this.routeMap = {}
// 将 current 注册为响应式对象
this.data = _Vue.observable({
current: '/'
})
}
init(){
this.createRouteMap()
this.initComponents(_Vue)
this.initEvent()
}
createRouteMap(){
// 遍历所有的路由规则,把路由规则解析成键值对的形式 存储到 routeMap 中
this.options.routes.forEach(route=>{
this.routeMap[route.path] = route.component
})
}
initComponents(Vue){
const self = this
Vue.component('route-link', {
props: {
to: String
},
render(h){
return h('a', {
attrs: {
href: this.to
},
on: {
click: this.clickHandler
}
}, [this.$slots.default])
},
methods: {
clickHandler(e){
// 取消默认行为
e.preventDefault()
// pushState 改变地址栏,但是不向服务器发送请求
history.pushState({}, '', this.to)
// 当前路径记录到 current 里边
this.$router.data.current = this.to
}
}
// template: '<a :href="to"><slot></slot></a>'
})
Vue.component('router-view',{
// 由于 current 是响应式的,所以这里会自动渲染对应的组件
render(h){
const component = self.routeMap[self.data.current]
return h(component)
}
})
}
initEvent(){
// 点击浏览器的前进后退按钮触发
window.addEventListener('popstate', ()=>{
this.data.current = window.location.pathname
})
}
}
完整代码
/**
* VueRouter Class
* -------------------------------------
* + options
* + data
* + routeMap
* -------------------------------------
* + Constructor(Option): VueRouter
* _install(Vue): void
* + init(): void
* + initEvent: void
* + CreateRouteMap(): void
* + initComponents(Vue): void
*/
export default class VueRouter{
static install(Vue){
// 1.判断当前插件是否被安装
if(VueRouter.install.installed){
return
}
VueRouter.install.installed = true
// 2.把 Vue 构造函数记录到全局变量
_Vue = Vue
// 3.把创建 Vue 实例的时候传入的 router 对象注入到 Vue 实例上
// 混入
_Vue.mixin({
beforeCreate(){
// router 执行,组件不执行
if(this.$options.router){
_Vue.prototype.$router = this.$options.router
this.$options.router.init()
}
}
})
}
constructor(options){
this.options = options
this.routeMap = {}
// 将 current 注册为响应式对象
this.data = _Vue.observable({
current: '/'
})
}
init(){
this.createRouteMap()
this.initComponents(_Vue)
this.initEvent()
}
createRouteMap(){
// 遍历所有的路由规则,把路由规则解析成键值对的形式 存储到 routeMap 中
this.options.routes.forEach(route=>{
this.routeMap[route.path] = route.component
})
}
initComponents(Vue){
const self = this
Vue.component('route-link', {
props: {
to: String
},
render(h){
return h('a', {
attrs: {
href: this.to
},
on: {
click: this.clickHandler
}
}, [this.$slots.default])
},
methods: {
clickHandler(e){
// 取消默认行为
e.preventDefault()
// pushState 改变地址栏,但是不向服务器发送请求
history.pushState({}, '', this.to)
// 当前路径记录到 current 里边
this.$router.data.current = this.to
}
}
// template: '<a :href="to"><slot></slot></a>'
})
Vue.component('router-view',{
// 由于 current 是响应式的,所以这里会自动渲染对应的组件
render(h){
const component = self.routeMap[self.data.current]
return h(component)
}
})
}
initEvent(){
// 点击浏览器的前进后退按钮触发
window.addEventListener('popstate', ()=>{
this.data.current = window.location.pathname
})
}
}
注意这里只是模拟一下原理,里边还有其他的条条框框的限制判断等等其他处理就不完善了