vue-router
基础
vue-router 大家都不陌生,它是vue中核心生态之一。
-
两种模式:hash 和history模式
-
两个组件 router-link 和router-view
-
两个常用方法属性
this.$router和this.$routesthis.$router路由跳转。this.$routes获取路由传参。
-
三种导航钩子。
- 全局导航钩子。
- 路由独享导航钩子。
- 组件导航钩子。
导航钩子的实现过于复杂,如果想探究vue-router的真正源码,可以参考 juejin.cn/post/684490…
简易实现
核心
hash 模式主要依赖监听hashchange方法。
使用Vue.Component 注册组件
使用Vue.util.defineReactive 将router置为响应式数据,一旦路径更新就可以更新视图
基础代码
const HASH='hash',HISTORY='history';
class History{
constructor(current){
this.current=current||'/home';
}
}
class VueRouter{
constructor(options){
//模式
this.mode=options.mode ||HASH;
let routes=options.routes || [];
this.routesMap=this.handleRoutes(routes);
this.history=new History();
this._init();
}
/**
* 初始化
*/
_init(){
if(this.mode===HASH)
{
location.hash?'':location.hash='#/';
//hash chanage
window.addEventListener('hashchange',()=>{
this.history.current=location.hash.slice(1);
})
window.addEventListener('load',()=>{
this.history.current=location.hash.slice(1);
})
}
else if(this.mode===HISTORY)
{
location.pathname?'':location.pathname='/'
window.addEventListener('popstate',()=>{
this.history.current=location.pathname;
})
window.addEventListener('load',()=>{
this.history.current=location.pathname;
})
}
}
handleRoutes(routes){
var routesMap=routes.reduce((res,current)=>{
res[current.path]=current.component;
return res;
},{});
console.log(routesMap);
return routesMap;
}
}
/**
* 安装
* @param {*} Vue
*/
VueRouter.install=(Vue)=>{
Vue.mixin({
beforeCreate(){
//获得唯一的 router 实例
//跟组件
if(this.$options && this.$options.router)
{
this._root=this.$options.router ||{};
// 将 _route 添加监听,当修改 history.current 时就可以触发更新了
Vue.util.defineReactive(this, '_route', this._root.history)
}
else{
//子组件
this._root=this.$parent && this.$parent._root||{};
}
console.log(this._root);
Object.defineProperty(this,'$routes',{
get(){
return this._self._root
}
})
Object.defineProperty(this,'$router',{
get(){
return this._self._root.history.current;
}
})
}
})
//路由跳转
Vue.component('router-link',{
props:{
to:String,
required:true
},
render(h)
{
let mode=this._self._root.mode,to=this.to;
return <a href={mode===HASH?`#${to}`:to}>{this.$slots.default}</a>
}
})
//注册路由容器组件
Vue.component('router-view',{
render(h)
{
console.log(this._self)
let current=this._self._root.history.current;
if(!current)
{
return;
}
let component=this._self._root.routesMap[current];
return h(component)
}
})
}
export default VueRouter;
结语
此处仅仅对vue-router的简易模拟,与真实源码相比差之千里,并无实际意义,不过简易实现可以让我们更加清楚其实现原理。以上是我学习中理解,如有错误,请谅解,欢迎批评指正。