从头开始学Vue-Router

742 阅读7分钟

前言

Vue-Router提出来是为了解决什么问题,跟以前写a标签或者重新打开一个浏览器窗口有什么不同,有什么优势,它的实现原理是什么等等带着这些问题我们来深入了解一下Vue-Router。

背景

以前我们打开页面一般都是用a标签或location.herf或window.open等方式,我们发现有时候每打开一个页面都会有点卡,因为我们每打开一个浏览器窗口都会重新加载所需要的资源包括公共css、js、图片等等,很多页面都加载的是同样的公共资源,这样子就会造成浏览器性能的大量消耗,并且前端重复的代码非常多,因为代码不能复用,比如头部或者底部很多html文件都要写一份,很不利于维护,特别是遇到复杂项目的时候,工作量成倍增加。为了注重用户体验(降低浏览器性能损耗)、开发大型复杂的项目(组件化,不需要重复写大量的代码)这两个主要难题的时候,单页面应用被提了出来。

单页面应用(SPA)

单页面应用是指只有一个页面的应用,在浏览器中运行期间不会重新加载页面,之后所有的交互操作都在一个页面上完成,这些都是通过vue-router切换不同的vue组件来显示不同的组件内容。公共资源(js、css等)仅需加载一次且一次全部加载,所以会有首屏问题,就是第一次打开页面有点慢,多页面应用是按需加载公共资源,所以没有首屏问题。 如图:

image.png
从上图我们可以看到Page-One、Page-Two、Page-Three共用一个Header和Footer。

多页面应用(MPA)

多页面跳转重新加载页面,所需公共资源(js、css等)会重新加载,所以很多页面都会加载相同的公共资源,造成浏览器性能的巨大浪费。 如图:

image.png
从上图我们可以看到Page-One、Page-Two、Page-Three每个页面都需要分别写一个Header和Footer造成大量代码重复。

具体对比分析:
单页面应用 多页面应用
组成 一个index.html页面和若干组件组成 多个完整页面构成
资源共用(css、js、img等) 共用,只需要在index.html页面加载 不共用,每个页面都需要加载
刷新方式 页面局部刷新或更改 整页刷新
url模式 a.com/#/pageone a.com/#/pagetwo a.com/pageone.html a.com/pagetwo.html
用户体验 页面组件的切换快,用户体验好 页面之间的切换加载缓慢,流畅度不够,用户体验比较差
转场动画 容易实现 无法实现
数据传递 容易 依赖url传参、cookie、localStorage等
搜索引擎优化(SEO) 需要单独方案、实现较为困难、不利于SEO检索,可利用服务器端渲染(SSR)优化 实现方法简易
试用范围 高要求的体验度、追求界面流畅的应用 适用于追求高度支持搜索引擎的应用
开发成本 较高,常需借助专业的框架 较低,但页面重复代码多
维护成本 相对容易 相对复杂

从上图我们可以看到单页面应用的优势和劣势:

单页面应用的好处
  • 用户体验好,快,内容的改变不需要重新加载整个页面,基于这一点SPA对服务器压力较小。从性能和用户体验的层面来比较的话,后端路由每次访问一个新页面的时候都要向服务器发送请求,然后服务器再响应请求,这个过程肯定会有延迟。而前端路由在访问一个新页面的时候仅仅是变换了一下路径而已,没有了网络延迟,对于用户体验来说会有相当大的提升。
  • 单页面应用没有页面之间的切换,就不会出现"白屏现象",也不会出现假死并有"闪烁"现象。
  • 良好的前后端分离。后端不再负责模版渲染、输出页面工作,只需要出数据就可以,后端API通用化,即同一套后端程序代码,不用修改就可以用于web界面、手机、平板等客户端。
单页面应用的缺点
  • 首次加载耗时比较多:为实现单页Web应用功能及显示效果,需要在第一次打开页面的时候将所有公共资源JavaScript、CSS、图片等一起加载,所以会有首屏问题,就是第一次打开页面有点慢。
  • SEO难度较高:搜索引擎爬虫工具只会爬取到后端返回的html内容(不支持ajax数据的爬取也就是不能爬取接口返回的数据),单页面应用只会在第一次进入页面的时候会向后端请求html文件,这时候会被搜索引擎爬虫工具检索到,但是在切换组件的时候是不需要向后端发送请求html文件的,所以是无法被爬虫工具检索到的,多页面应用每次页面跳转后端服务器都会返回一个新的html文档,会被爬虫工具检索到。 针对以上两个缺点vue又提出了SSR来解决。

Vue-Router原理

这里的路由是SPA的路径管理器。Vue-Router是Vue.js官方的路由插件,它和Vue.js是深度集成的,适合于构建单页面应用。Vue的单页面应用是基于路由和组件的,路由用于设定访问路径,并将路径和组件映射起来。传统的页面,是通过超链接来实现页面跳转,在Vue-Router单页面应用中,则是路径之间的切换,也就是组件的切换。Vue路由的本质就是建立起hash路由和组件之间的映射关系。 单页面应用的核心之一是更新视图而不重新请求页面,Vue-Router在实现单页面应用前端路由时,提供了两种方式:Hash模式和History模式,根据mode参数来决定采用哪一种方式,这两种方式都不会让页面重新加载。

Hash模式:

我们经常在url中看到#,这个#有两种作用,一种用来实现锚点功能,一种用来做hash路由,hash是#号后面的部分,单单改变#后的部分是不会刷新页面,不会重新加载页面,同时每一次改变#后的部分,都会在浏览器的访问历史中增加一条记录,使用后退按钮就可以回到上一个页面,Vue-Router就是利用这一点来实现前端路由。主要原理是通过监听 # 后的 URL 路径标识符的更改而触发的浏览器 的hashchange 事件,然后通过获取 location.hash 得到当前的路径标识符,再进行一些路由跳转的操作。

History模式

由于hash模式会在url中自带#,如果不想要很丑的 hash,我们可以用路由的 history 模式,只需要在配置路由规则时,加入"mode: 'history'",这种模式充分利用了html5 history interface 中新增的 pushState() 和 replaceState() 方法。这两个方法应用于浏览器记录栈,在当前已有的 back、forward、go 基础之上,它们提供了对历史记录修改的功能。只是当它们执行修改时,虽然改变了当前的 URL ,但浏览器不会立即向后端发送请求。

//main.js文件中
const router = new VueRouter({
  mode: 'history',
  routes: [...]
})

当你使用 history 模式时,URL 就像正常的 url,如 yoursite.com/user/id,看上去… oursite.com/user/id就会返回 404,这就不好看了。所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。

 export const routes = [ 
  {path: "/", name: "homeLink", component:Home}
  {path: "/register", name: "registerLink", component: Register},
  {path: "/login", name: "loginLink", component: Login},
  {path: "*", redirect: "/"}]

此处就设置如果URL输入错误或者是URL 匹配不到任何静态资源,就自动跳到到Home页面。

Vue-Router可以用来管理哈希路由、传递数据

路由源码:juejin.cn/post/684490… mp.weixin.qq.com/s/xVDUtqA-V…