当前位置: 首页 > Web前端 > JavaScript

手写vue-router核心原理

时间:2023-03-27 17:35:51 JavaScript

最近也在观察vue3的新特性,抽空玩玩嵌套路由的vue-router,直接进入代码项目目录结构代码展示app.vueIndex.vuePerson.vuePersonInfo.vuejs文件main.jsimportVuefrom'vue'importAppfrom'./App.vue'importrouterfrom'./router'newVue({router,render:h=>h(App)}).$mount('#app')babel.config.js需要添加babel依赖来支持新的语法,比如optionalchainnpminstall--save-dev@babel/core@babel/clinpminstall--save-dev@babel/plugin-proposal-optional-chainingmodule.exports={预设:['@babel/preset-env'],插件:['@babel/plugin-proposal-optional-chaining']}路由器目录下的文件index.js从“vue”导入Vue;从“./vue-router”导入VueRouter;从“../views/Index.vue”导入Index;从“../views/”导入PersonPerson.vue";从"../views/PersonInfo.vue"导入PersonInfo;Vue.use(VueRouter);constroutes=[{path:"/",name:"Index",component:Index},{path:"/person",name:"Person",component:Person,children:[{path:"/person/info",name:"PersonInfo",component:PersonInfo}]}];constrouter=newVueRouter({routes});exportdefaultrouter;vue-router.js首先使用Vue的工具Vue.util.defineReactive实现数据responsiveness,然后手工撕掉这个库current=window.location.hash.slice(1)||"/"//设置响应式数组数据Vue.util.defineReactive(this,"routerArray",[])//监听哈希值变化window.addEventListener("hashchange",this.hashChange.bind(this))this.getRouterArray()}hashChange(){this.current=window.location.hash.slice(1)||"/"this.routerArray=[]this.getRouterArray()}getRouterArray(routes){routes=routes||this.$options.routesfor(constrouteofroutes){if(this.current==='/'&&route.path==='/'){this.routerArray.push(route)return}if(this.current.indexOf(route.path)!==-1&&route.path!=='/'){this.routerArray.push(route)if(route.children){//递归子路由this.getRouterArray(route.children)}return}}}}VueRouter.install=function(_Vue){Vue=_Vue//全局混入vue,等待routerinstancein要创建的新Vue然后将其挂载到VueVue.mixin({beforeCreate(){if(this.$options.router){Vue.prototype.$router=this.$options.router}},});//注册router-link和router-view全局组件Vue.component("router-link",routerLink)Vue.component("router-view",routerView)}exportdefaultVueRouter参考前端面试题详解router-link.jsexportdefault{props:{to:{type:String,required:true}},render(h){returnh("a",{attrs:{href:"#"+this.to,},},this.$slots.default);}};router-view.jsexportdefault{render(h){//设置嵌套路由标识符this.$vnode.data.rv=true//设置嵌套路由的深度letdepth=0letparent=this.$parentwhile(parent){//parent有嵌套路由标志rv为真,深度加一if(parent.$vnode?.data?.rv){depth++}parent=parent.$parent}//简单处理constroute=this.$router.routerArray[depth]returnh(route?.component);}};效果图做好了,今天先玩到这里,下次再玩其他游戏