vue-router手写、 vue-router原理

vue路由有三种模式:hash history和abstract:
hash:使用URL hash值作路由,支持所有浏览器
history:需要HTML5 History API和服务器配置结合。对浏览器版本有要求,不支持低版本
abstract:支持所有js运行环境。如果当前环境没有浏览器API,路由会自动进入这个模式
我们在vue项目中,是怎么使用vue-router的呢?
首先,要从npm install vue-router -g 在系统中安装router插件,然后新建router文件在文件中通过 import 引入,新建好route目录后对外导出,在main.js中引入,挂载到vue中,即可使用
import Vue for "vue"
import Router from "vue-router"
Vue.use(Router)
let router =new Router({......})
export default router

main.js中引用如下

import Vue from "vue"
import router from "./router/router"

new Vue({
	router,
	render:h=>h(App)
}).$mount("#app")

要自己手写一个router方法那么,通过上面的一系列操作得知,自己写的属于一个插件,要通过vue.use()使用,那么我们在插件中必须提供一个install方法,并对外暴露

class myRouter{
	constructor(options){
		this.$options=options
		this.routerMap={} //保存router列表
        // 使用vue的响应式机制,使路由切换的时候 进行相应
        this.app=new Vue({
            data:{
                // 默认为根目录
                current:"/"
            }
        })
	}
	static install(_Vue){
		......
	}
}

做好一个路由,需要明确需求是什么,首先要监听路由变化,其次处理router.js中设置的路由列表,还有初始化路由组件

//由此可以设置一个init函数用为罗列我们需要完成的需求
init(){//负责启动整个路由
	//1.监听路由变化
	this.bindRouterEvent()
	//2.处理路由列表
	this.createRouterList()
	//3.初始化路由组件 router-view router-link
	this.setComponent()
}

下面来监听一下路由变化,此处可以直接window直接hashchange事件hashchange

bindRouterEvent(){
	window.addEventListener("hashchange",this.beginChange.bind(this),false)
	//初始化时同样需要监听
	window.addEventListener('load',this.onHashChange.bind(thsi),false)
}
beginChange(event){
	//获取当前hash值
	let hash = window.location.hash.slice(1) || '/';
	//将hash值写入
	this.app.current=hash
}

当前已经监听到了hash的变化,获取到了hash值,接下来,处理一下已经配置好的路由列表

createRouterList(){
	//在constructor中已经将option保存到了$option中,在此我们直接取用
	this.$options.routes.forEach(item=>{
		//将当前数组路由转为字典对象 方便查询
       this.routerMap[item.path]=item
    })
}

已经完成了监测hash变化和获取路由列表,下面我们需要注册组件,然后就可以应用了

setComponent(){
	Vue.component('router-view',{
            render:h=>{
                // this.app.current 是我们默认的路由
                const component = this.routerMap[this.app.current].component
                //使用h新建一个虚拟dom
                return h(component)
            }
        })
        Vue.component('router-link',{
            props:{
                to:String //vue自带的参数校验
            },
            //动态显示的时候 依然推荐用render 更快更强
            render(h){
                // h三个参数 h=createElement
                // 组件名
                // 参数
                // 子元素
                return h('a',{
                    attrs:{
                        href:`#${this.to}`
                    }
                },
                [this.$slots.default]//插槽
                )
                
            }
            //template最终是转换成render执行 但是会多一层编译
            // template:"<a :href='to'> <slot></slot> </a>" 解析不成功
        })
}

除了router-view 和 router-link,还有一种常用的push方法来改变路由,从而访问其它页面,这里可以直接写入

push(url){
    // hash模式直接赋值
    window.location.hash=url
}

最后,要在前面写好的install中整体调用一下

static install(_Vue){
	Vue=_Vue
	Vue.mixin({
		beforeCreate(){
			if(this.$options.router){
				//将定义好的路由放到vue的prototype中,这样可以在任何页面使用push方法改变路由
				//把整个router对象挂载到vue原型链上,这样内部可以通过this.$router来获取路由实例
				Vue.prototype.$myrouter=this.$option.router
				this.$option.router.init()
			}
		}
	})
}

vue-router 还有一些生命周期的设置,目前还没有写好,可以在监听hash变化的时候做判断,感兴趣的话可以先自己完善一下。

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页