当前位置: 首页 > Web前端 > vue.js

通过vue-router源码学习vue

时间:2023-04-01 01:31:51 vue.js

vue-router是vue官方支持的,算是vue.js1的最佳实践。VueRouter类构造函数createMatcher解析路由配置、路径、层级等;根据mode、fallback配置和浏览器history.pushState支持创建对应的history实例(push、replace、go等方法,通过操作history实现);init方法暴露了addRoutes、push、replace、go等路由操作方法;暴露beforeEach、beforeResolve、onReady等钩子函数;2、VueRouter类增加了install方法。该方法第一个参数为Vue构造函数,第二个参数为一个Optional选项对象(Vue插件);src/install.jsVueRouter类的install方法判断Vue是否初始化了Vue-router;注册和销毁是在Vue.mixin中全局混入实现的,使用全局混入会影响后面每一个创建的VueInstance(Vueglobalmixin)。在beforeCreate中this指向Vue组件实例,所有的组件beforeCreate声明循环都会调用这个函数;this.$options.router指的是newVue时传入的Vue-router实例,this.$options.router不为空,说明此时this指向Vue根组件实例;newVue({router,//this.$options.router不为空,说明this指向Vue根组件实例render:h=>h(App)}).$mount('#app')this._routerRoot指向Vue根组件实例,后续所有子组件实例的_routerRoot指向this.$parent._routerRoot,所有子组件的_routerRoot以逐层方式指向根组件实例层转移;添加一个Vue实例属性$router和$route是通过将它们添加到Vue.prototype来实现的。这里只通过Object.defineProperty设置了get方法,防止修改。这样所有的组件都可以通过this.$router和this.$route来操作路由,获取当前的路由信息??。声明全局组件RouterView和RouterLink设置选项合并策略(自定义选项合并策略)src/history/base.jsHistory类,HashHistory和HTML5History都继承自该基类定义go、push、replace、ensureURL、getCurrentLocation方法,由子类决定实现构造函数,初始化属性,处理标签src/components/link.js全局组件RouterLink默认渲染为标签tag:{type:String,default:'a'}默认事件是点击事件回调handler先通过guardEvent过滤掉一些事件,然后跳转consthandler=e=>{if(guardEvent(e)){if(this.replace){router.replace(location,noop)}else{router.push(location,noop)}}}tag属性为a,则事件直接绑定到组件上if(this.tag==='a'){data.on=on}修改标签,首先寻找默认槽(Vue命名插件如果槽中有标签),就会绑定到第一个找到的标签,如果没有找到,它会直接绑定到组件if(this.tag==='a'){...}else{//找到第一个childandapplylistenerandhrefconsta=findAnchor(this.$slots.default)if(a){//appendnewlistenersforrouter-link...}else{//没有child,applylistenertoselfdata.on=on}}src/组件s/view.js全局组件RouterView,功能组件(Vue功能组件)标记routerview,方便确认level//devtools用来显示一个router-viewbadgedata.routerView=true值得注意的是render函数并没有使用自己的createElement方法,而是使用parent的parent.$createElement节点。Remarks大致意思是解析namedslot//直接使用parentcontext的createElement()函数//这样router-view渲染的组件就可以解析namedslotconsth=parent.$createElement确认路由级别,处理parent组件keepAlive//确定当前视图深度,同时检查树//是否已切换为非活动状态但保持活动状态。letdepth=0letinactive=false//parent._routerRoot!==parent表示父级不是Vue根组件实例//参考.js中的src/installbeforeCreate方法while(parent&&parent._routerRoot!==parent){constvnodeData=parent.$vnode?parent.$vnode.data:{}if(vnodeData.routerView){//如果只是想确认路由级别,这里可以depth=vnodeData.routerViewDepth+1;休息;depth++}if(vnodeData.keepAlive&&parent._directInactive&&parent._inactive){inactive=true}parent=parent.$parent}data.routerViewDepth=深度