1。路由的来源其实就是url和文件的映射。当后端控制路由收到客户端的http请求后,会根据响应的url进行查找。执行相应的映射函数,得到返回值给客户端。对于简单的静态资源服务,所有url的映射函数都是文件读取操作;对于动态资源,映射函数可能是数据库读取操作,也可能是一些数据处理等。然后根据读取数据的路径,服务器使用相应的模板渲染页面后,返回渲染后的页面。服务端控制路由,实现服务端渲染。服务端渲染的优缺点是:优点:安全性好,容易SEO,可以提高前端页面的渲染速度缺点:会增加服务器的压力,代码冗余不易维护,不利于用户体验。服务器端控制路由本质上是url和文件读取操作的映射,而前端路由是显示和隐藏dom元素,访问不同路径时显示不同的组件。目前前端路由的实现方式主要有两种:hash模式和history模式。前端路由的优缺点是:缺点:不利于SEO,使用浏览器的前进后退键时会重新发送请求,没有合理使用缓存优点:交互体验好,用户做不需要刷新页面,页面显示流畅,不错前后端工作分离模式减轻服务器压力2、两种路由模式的区别和原理?Vue-router有两种路由模式,分别是hash模式和history模式。路由配置中默认的是哈希模式。hash模式的前端路由早期是基于location.hash实现的。为此,react-router和vue-router都默认使用哈希路由作为路由方式。hash方式的url默认带#,location.hash的值为url中#后面的内容。在vue-router中,对于https://img.ydisp.cn/news/20220901/hpt353b3srbdata-id="ucd67dc5-dK6pY6RG">hash值会存储在客户端的url中,但不会出现在URL发送到服务端的http请求中,即不会发送hash;哈希值得更改,页面不会重新加载,而只是在浏览器的访问历史记录中添加一条记录。其实就是在栈结构中添加和删除数据。实现浏览器前后控制哈希切换;hash模式对浏览器的兼容性更好,也是SPA单页应用的标准配置。使用:切换hash路由有两种方式。使用a标签设置href属性,在用户点击后触发url变化,即触发hashchange事件search;直接用js实现给location.hash赋值改变url,触发hashchange事件location.hash="#search"。对此,可以看到hash路由的实现是基于对hashchange事件的监控。原理:hash模式的主要原理是onhashchange()事件:window.onhashchange=function(event){console.log(event.oldURL,event.newURL);lethash=location.hash.slice(1);}使用onhashchange()的优点:当页面的hash值发生变化时,窗口可以监听到事件的变化,并根据规则加载相应的代码,而无需发起一个向后台请求;hash值变化对应的URL会被浏览器记录下来。这样浏览器就可以实现页面的前进和后退。没有请求到后端服务器,而是将页面的哈希值关联到相应的URL。history模式的url没有#,看起来比hash模式漂亮。本质是通过传统的路由分发模式,即当用户输入一个url,服务端会收到请求并解析该url,然后做相应的逻辑。处理。使用历史模式时,URL是这样的:https://blog.onechuan.cn/user/id。特点:history模式的url比hash模式的url更漂亮;history模式需要服务端有相应的配置支持,否则返回时会返回404;pushState和replaceState的标题(title):一般浏览器会忽略。最好传入null;可以使用popstate事件监听url的变化;原理:历史模式主要依赖两个API:history.pushState()和history.repalceState()来实现浏览器不刷新历史记录的操作。修改历史状态:history.pushState()和history.repalceState()提供了修改历史的功能。只是当他们修改的时候,虽然修改了url,但是浏览器并没有立即向后端发送请求。如果想实现改变url不刷新页面的效果,就需要在前端使用这两个API。切换历史状态:包括forward()、back()、go()三个方法,对应浏览器的前进、后退、跳转操作pushState和repalceState不会触发popstate事件,这时我们需要手动触发页面渲染。缺点:刷新页面时,如果没有对应的路由或资源,会显示404。两种路由模式对比Hash模式History模式原理onhashchange()history.pushState()和history.repalceState()兼容性>=ie8,其他主流浏览器>=ie10,其他主流浏览器不实用需要make更改服务器,需要服务器配置支持。3、如何获取页面的hash变化?通过在$route中监听变化//监控,当路由变化时执行watch:{$route:{handler:function(val,oldVal){console.log(val);},//深度观察和倾听deep:true}}通过js的window.location.hash读取#value。window.location.hash的值是可读可写的。读取它来判断状态是否发生了变化。写的时候可以添加一个历史记录,不用重载网页访问记录。4、Vue-Router是如何实现路由的懒加载的?使用箭头函数+import动态加载constList=()=>import('@/components/list.vue')constrouter=newVueRouter({routes:[{path:'/list',component:List}]});使用箭头函数+require动态加载constrouter=newRouter({routes:[{path:'/list',component:resolve=>require(['@/components/list'],resolve)}]});这种情况下,利用webpack的require.ensure技术,将指定相同chunkName的多条路由合并,打包成一个js文件。//risresolveconstList=r=>require.ensure([],()=>r(require('@/components/list')),'list');//路由也是正常的写法这是官方推荐写延迟加载的模块constrouter=newRouter({routes:[{path:'/list',component:List,name:'list'}]}));5.$route和$router的区别?$route是一个“路由信息对象”,包括path、paramshash、query、fullPath、matched、name等路由信息参数;$router是一个“路由实例”对象,包括路由跳转方法、钩子函数等。6.如何定义动态路由?如何获取传递的动态参数?Param方式配置路由格式:/router/:id投递方式:按照相应值投递形成的路径跟随路径:/router/123定义动态路由//inAPP.vueUser//router.js中{path:'/user/:userid',component:User,}路由跳转//方法一:button//方法二:this.$router.push({name:'users',params:{uname:onechuan}})//方法三:this.$router.push(`/user/${onechuan}`);参数通过$route.params.userid获取传递的值。查询方式配置路由格式:/router,即普通配置传递方式:以对象中的querykey构成的路径作为传递方式:/route?id=123routedefinition//方法一:直接在router-linklabelfile//方法2:写成按钮点击事件表单profileClick(){this.$router.push({path:"/profile",query:{name:"kobi",age:"28",height:198}});}跳转方法//方法一:button//方法二:this.$router.push({name:'users',query:{uname:james}})//方法三:button//方法四:this.$router.push({path:'/user',query:{uname:james}})//方法五:this.$router.push('/user?uname='+james)获取参数并获取传值t通过$route.query。7.params和query有什么区别?相比之下,paramsquery的导入方法是使用name来引入,使用path来导入接收参数。参考,url显示参数刷新页面params刷新会丢失params查询中的数据刷新不会丢失查询中的数据8.Vue-router路由钩子在生命周期中如何体现?完整的路由导航解析过程(不包括其他生命周期)会触发进入其他路由。调用要离开路由的组件GuardbeforeRouteLeave调用前端守卫:beforeEach在复用组件中调用beforeRouteUpdate调用路由独占守卫beforeEnter。解析异步路由组件。在待进入的路由组件中调用beforeRouteEnter调用全局解析守卫beforeResolve导航确认。调用全局afterhook的afterEachhook。触发DOM更新(挂载)。执行在beforeRouteEnter守卫中传递给next的回调函数会触发完整的挂钩序列。路由导航、保活、组件生命周期钩子组合在一起。触发顺序假设是第一次从a组件离开,进入b组件:beforeRouteLeave:路由组件的组件离开路由前的钩子,可以取消路由离开。beforeEach:路由全局前卫,可用于登录验证,全局路由加载等。beforeResolve:路由全局解析守卫afterEach:路由全局post-hookbeforeCreate:组件生命周期,不能访问tAis。创建;组件生命周期,可以访问tAis,不能访问dom。beforeMount:componentlifecycledeactivated:离开缓存组件a,或者触发a的beforeDestroy和destroyed组件销毁钩子。安装:访问/操作dom。activated:进入缓存组件,进入a的嵌套子组件(如果有的话)。接下来执行beforeRouteEnter回调函数。整个过程都会触发导航行为,直到导航完成,此时不确认导航。在停用的组件中调用离开守卫beforeRouteLeave。调用全局beforeEach守卫。在可重用组件中调用beforeRouteUpdate守卫(2.2+)。在路由配置中调用beforeEnteY。解析异步路由组件(如果有)。在激活的组件中调用beforeRouteEnter。调用全局beforeResolve守卫(2.5+)来标记解析阶段的完成。导航已确认。调用全局afterEach挂钩。不可重用的组件,开始组件实例的生命周期:beforeCreate&created,beforeMount&mounted触发DOM更新。使用创建的实例在beforeRouteEnter守卫中调用传递给next的回调函数。导航完成9.Vue-router导航守卫有哪些?全局front/hook:beforeEach,beforeResolve,afterEach路由独享守卫:beforeEnter组件中的守卫:beforeRouteEnter,beforeRouteUpdate,beforeRouteLeaveVue-RouterNavigationguards用于一些场景,比如:最常见的登录权限验证,当用户遇到条件,让它进入导航;否则取消跳转,跳转到登录页面让它登录。为此,路由导航过程的植入方式有很多种:全局单路由独占组件级全局路由钩子vue-router全局有3个路由钩子;router.beforeEach全局pre-guard,router.beforeResolve在进入路由前全局解析guard(2.5.0+),在调用beforeRouteEnter后调用router.afterEach全局post-hook,进入路由后使用:beforeEach(判断是否已登录,未登录则跳转到登录页面)afterEach(跳转滚动条回到顶部后)router.beforeEach((to,from,next)=>{letifInfo=Vue.prototype.$common.getSession('userData');//存储判断是否登录的信息if(!ifInfo){//sessionStorage中没有存储用户信息if(to.path=='/'){//如果是登录页面路径,就next()next();}else{//否则跳转到登录Message.warning("Pleaseloginagain!");window.location.href=Vue.prototype.$loginUrl;}}else{returnnext();}});router.afterEach((to,from)=>{//跳转后滚动条回到顶部window.scrollTo(0,0);});单个路由的独占hookbeforeEnter如果不想全局配置守卫,可以对部分路由单独配置守卫,三个参数:to、from、nextexportdefault[{path:'/',name:'login',component:login,beforeEnter:(to,from,next)=>{console.log('即将进入登录页面')next()}}]组件中的三个hook,beforeRouteUpdate、beforeRouteEnter、beforeRouteLeave,都有三个参数:to,from,nextbeforeRouteEnter:在进入组件前触发beforeRouteUpdate:当前地址改变,组件被复用时触发,比如动态参数的路由foo/:id,在/foo/1和/之间foo/2之间跳转的时候,因为会渲染同一个foa组件,所以会调用这个hookbeforeRouteLeave这种情况下:调用left组件注意这个不能在beforeRouteEnter组件中访问,因为守卫执行之前的组件实例还没有创建,需要传一个回调给next来访问,例如:beforeRouteEnter(to,from,next){next(target=>{if(from.path=='/classProcess'){target.isFromProcess=true}})}10.vue-router跳转和location.href有什么区别?使用location.href=/url跳转,简单方便,但刷新页面;使用history.pushState(/url),不刷新页面,静态跳转;引入router,然后使用router.push(/url)跳转,使用diff算法实现按需加载,减少dom的消耗其实使用router跳转和使用history.pushState()没有区别,因为vue-router使用了history.pushState(),尤其是在history模式下。参考文章https://img.ydisp.cn/news/20220901/g5inpr5ibh5