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

VUE-Router

时间:2023-04-06 00:23:22 HTML5

githubvue-router的简单实现Vue-router是Vue.js官方的路由管理器。它与Vue.js的核心深度集成,可以轻松构建单页应用程序。安装vue添加路由器核心步骤第一步:使用vue-router插件//router.jsimportRouterfrom'vue-router';VueRouter是一个插件1)实现并声明两个组件router-viewrouter-link2)install:this.$router.push()*/Vue.use(Router);//导入插件Step2:创建一个Router实例//router.jsexportdefaultnewRouter({...})//导出一个Router实例Step3:在根组件中添加这个实例//main.jsimportrouterfrom'./router';newVue({router//添加到配置项}).$mount("#app")第四步:添加路由视图第5步:导航主页关于this.$router.push('/');this.$router.push('/about')Vue-router简单实现需求分析在单页应用中,当url改变时,无法刷新。显示对应viewhash:#/aboutHistoryapi:/about根据url显示对应内容router-viewdata响应类型:current变量保存url地址,一旦变化,动态执行render任务实现一个插件实现VueRouter类处理路由选项,监听url变化响应变化实现install方法$router注册两个全局组件新建插件在Vue2.x项目的src路径下,复制一个router文件,重命名它到你的路由器。然后在ou-router路径下新建ou-vue-router.js文件,将index.js文件中VueRouter的引入改为ou-vue-router.js。importVueRouterfrom'./ou-vue-router'修改main.js中router的引入。importrouterfrom'./ou-router'创建Vue插件关于Vue插件的创建:可以用函数实现,也可以用对象或类实现;要求有一个install方法,以后Vue.use()会用到letVue;//保存Vue的构造函数,插件需要使用classVueRouter{}插件:实现install方法,注册$router参数1为Vue.use()会被传递*/VueRouter.install=function(_Vue){Vue=_Vue;//引用构造函数,使用}exportdefaultVueRouterinVueRouter;###挂载`$router`当我们发现`vue-router`引入`vue`时,第一次在`router`Vue.use(Router)`中使用在/index.js`中,而`此时会调用vue-router的install方法;第二次是在`main.js`中,在创建根组件实例时引入`router`,即`newVue({router}).$mount("#app")`。也就是说,在调用`vue-router`的`install`方法时,项目还没有创建`Vue`的根组件实例。因此,我们需要在vue-router的install方法中使用全局mixin,等待router创建完成后再执行挂载$router。让Vue;//保存Vue构造函数,插件需要使用classVueRouter{}/*plugin:实现install方法,注册$router参数1为Vue.use()肯定会传入*/VueRouter.install=function(_Vue){Vue=_Vue;//引用构造函数,VueRouter应该使用/*mount$router*//**全局mixin*全局mixin的目的是延迟后面的逻辑,直到创建路由器并附加到选项**/Vue.mixin({beforeCreate(){//当每个组件创建一个实例时都会调用这个钩子/*this.$options是创建Vue实例的第一个参数*/if(this.$options.router){//只有router根组件中的选项Vue.prototype.$router=this.$options.router;//vm.$router}}})}exportdefaultVueRouter;###注册全局组件`router-link`和`router-view`首先在`install`方法中注册两个全局变量。让Vue;classVueRouter{}VueRouter.install=function(_Vue){Vue=_Vue;Vue.mixin({...})/*注册全局组件router-link和router-view*/Vue.component('router-link',{render(createElement){returncreateElement('a','router-link');//返回虚拟Dom}});Vue.component('router-view',{render(createElement){returncreateElement('div','router-view');//返回虚拟Dom}})}exportdefaultVueRouter;router-view是一个a标签,将router-view的to属性设置为a标签的herf属性(默认使用hash方式)获取router-view的slot内容,插入到a标签中的vue.component('router-link',{props:{to:{type:String,required:true}},render(createElement){//返回虚拟DomreturncreateElement('a',{attrs:{href:'#'+this.to}//设置标签的href属性},this.$slots.default//获取标签槽内容);}});实现router-viewrouter-view其实是根据url的变化实时响应相应的组件渲染,并创建Element函数可以传入一个组件参数。因此,我们不渲染任何内容。后来监听到url变化,从映射表中获取component,实现router-view。Vue.component('router-view',{render(createElement){letcomponent=null;returncreateElement(component);//returnvirtualDom}})监听url变化我们在VueRouter类的构造函数中监听url变化,这里我们默认使用hash方式。而且,我们需要将url中存储的变量设置为响应式数据,这样当它发生变化时,router-view的render函数可以重新执行。classVueRouter{/**options:*mode:'hash'*base:process.env.BASE_URL*routes**/constructor(options){this.$options=options;//设置current为响应数据,即当current发生变化时,router-view的render函数可以重新执行constinitial=window.location.hash.slice(1)||'/';Vue.util.defineReactive(this,'current',initial);//监听hashChangewindow.addEventListener('hashchange',()=>{this.current=window.location.hash.slice(1);})}}因此,我们可以实现router-view组件。在render函数中,this.$router指向VueRouter创建的实例,所以我们可以通过this.$router.$option.routes获取路由映射表,this.$router.current获取当前路由,然后获取它通过遍历匹配组件。Vue.component('router-view',{render(createElement){letcomponent=null;//获取当前路由对应的组件constroute=this.$router.$options.routes.find(route=>route.path===this.$router.current);if(route){component=route.component;}returncreateElement(component);//returnvirtualDom}})implementhistorymode之前的实现默认是hash模式,然后下来简单实现一下history模式。首先优化监听url的代码,确定mode的值设置为current的初始值,而historymode中的初始值为window.location.pathname。classVueRouter{/**options:*mode:'hash'*base:process.env.BASE_URL*routes**/constructor(options){this.$options=options;switch(options.mode){case'hash':this.hashModeHandle();休息;案例“历史”:this.historyModeHandle();}}//哈希模式处理hashModeHandle(){//设置current为响应式数据,即current变化时router-view的render函数可以再次执行constinitial=window.location.hash.slice(1)||'/';Vue.util.defineReactive(this,'current',initial);//监听哈希变化window.addEventListener('hashchange',()=>{this.current=window.location.hash.slice(1);})}//历史模式处理historyModeHandle(){constinitial=window.位置.路径名||'/';Vue.util.defineReactive(this,'current',initial);}}然后我们以history模式实现router-link组件。history模式下,当我们点击router-link,也就是点击a标签的时候,页面就会刷新。所以我们需要设置它的点击事件,取消默认事件,然后通过history.pushState修改url,再重新设置current的值。Vue.component('router-link',{render(createElement){//返回虚拟Domconstself=this;constroute=this.$router.$options.routes.find(route=>route.path===this.to);returncreateElement('a',{attrs:{href:this.to},//设置a标签的href属性on:{click(e){e.preventDefault();//取消a标签默认事件是刷新页面history.pushState({},route.name,self.to);//通过history.pushState改变urlself.$router.current=self.to;}}},this.$slots.default//获取标签槽内容);}})最后,我们合并两种模式的router-link组件。Vue.component('router-link',{props:{to:{type:String,required:true}},render(createElement){//返回虚拟Domif(this.$router.$options.mode==='hash'){returncreateElement('a',{attrs:{href:'#'+this.to}//设置a标签的href属性},this.$slots.default//获取内容标签槽的);}else{constself=this;constroute=this.$router.$options.routes.find(route=>route.path===this.to);returncreateElement('a',{attrs:{href:this.to},//设置a标签的href属性on:{click(e){e.preventDefault();//取消a标签的默认事件,即刷新页面history.pushState({},route.name,self.to);//通过history.pushState改变urlself.$router.current=self.to;}}},this.$slots.default//获取标签槽内容);}}});