现在很多项目的前端都是用vue单页实现的,而单页中最重要的环节就是路由。今天,我们将实现一个简单版本的vue-router。让我们来看看路由的工作流程。后端路由输入url请求发送给服务器,服务器解析请求的路径得到相应的数据-返回给前端。css渲染页面了解了路由工作流程之后,我们来看一下vue-router工作流程。url变化,触发监听事件改变vue-router的当前变量(新Router中的current变量),监听当前变量的monitor获取新组件,渲染新组件url变化,涉及到两个模式、散列和历史。hash的特点#hash后的内容只给浏览器,不给服务器。可以通过location.hash获取,可以通过onhashchange监听改变历史特征。历史,即正常的路径,可以通过location.pathname获取。onpopstate查看监控历史变化,查看router.js中的内容。实例化时会传入mode、routers等其他参数importhellofrom'./hello.vue';newRouter({mode:'history',routers:[{path:'/',name:'hello',component:hello}]})vueplugin查看vue插件的用法1.插件都是用Vue.use方法注册的,我们看下一段代码。//声明一个普通对象testvartest={b:1}//写一个定时器,2秒后改变test的b属性的值setTimeout(function(){test.b=111;},2000)//声明afunctionfunctiona(){console.log(1)}//AssignaninstallattributetoaMethoda.install=function(vue){//测试对象b属性的双向绑定vue.util.defineReactive(test,'b')//全局混合vue.mixin({beforeCreate(){this.test=test;}})}//注册插件aVue.use(a);
{{test.b}}
运行这段代码,结果会显示在第1页,2秒后变成111,从这个demo可以看出插件可以实现双向定义变量绑定。实现接下来实现一个简单的路由,看代码classHistoryRoute{constructor(){this.current=null;}}classvueRouter({constructor(opt){//路由模式this.mode=opt.mode||'hash';//路由配置项this.routes=opt.routes||[];this.history=newHistoryRoute;//将路由配置项从数组转换为键值对this.routesMap=this.createMap(this.routes);//初始化、获取和监听路由this.init()}init(){if(this.mode==='hash'){location.hash?"":location.hash="/";window.addEventListener('load',()=>{this.history.current=location.hash.splice(1);});window.addEventListener('hashchange',()=>{this.history.current=location.hash.splice(1)})}else{location.pathname?"":location.pathname="/";window.addEventListener('load',()=>{this.history.current=location.pathname;});window.addEventListener('popstate',()=>;{this.history.current=location.pathname})}}createMap(routes){returnroutes.reduce((memo,current)=>{memo[current.path]=current.component;returnmemo;},{})}})vueRouter.install=vue=>{vue.mixin({beforeCreate(){if(this.$options&&this.$options.router){this._root=this;this._router=this.$options.router;}//双向绑定当前变量vue.util.defineReactive(this,'current',this._router.history)}else{//嵌套路由this._root=this.$parent._root;}//定义this.$router的get方法,防止修改属性Object.defineProperty(this,'$router',{get(){returnthis._root._router;}})})//注册一个router-视图组件,渲染路由组件vue.component('router-view',{render(h){letcurrent=this._self._root._router.history.current;letroutesMap=this._self._root._router.肉测试地图;返回h(routesMap(current));}})}导出默认vueRouter;