博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(解析)单页应用路由实现没那么难--Vue
阅读量:5894 次
发布时间:2019-06-19

本文共 3366 字,大约阅读时间需要 11 分钟。

前言

单页Web应用(single page web application,SPA),就是只有一张Web页面的应用,是加载单个HTML 页面并在用户与应用程序交互时动态更新该页面的Web应用程序。简单来说就是用户只需要加载一次页面就可以不再请求,当点击其他子页面时只会有相应的URL改变而不会重新加载。

我们可以将实现路由的过程分为两部分:

  1. 更新URL页面不刷新
  2. 监听URL的变化,执行页面替换逻辑

现在主流有2种实现方案:

  1. history.pushState等触发popstate事件
  2. location.hash的变化触发hashchange事件

接下来我们一步一步看Vue-router如何实现的

Vue-router源码解剖

构造器

请各位同学翻到 src/index.js 第18行

export default class VueRouter {  static install: () => void;  static version: string;  app: any;  apps: Array
; ready: boolean; readyCbs: Array
; options: RouterOptions; mode: string; history: HashHistory | HTML5History | AbstractHistory; matcher: Matcher; fallback: boolean; beforeHooks: Array
; resolveHooks: Array
; afterHooks: Array
; constructor (options: RouterOptions = {}) { this.app = null this.apps = [] this.options = options this.beforeHooks = [] this.resolveHooks = [] this.afterHooks = [] this.matcher = createMatcher(options.routes || [], this) let mode = options.mode || 'hash' this.fallback = mode === 'history' && !supportsPushState && options.fallback !== false if (this.fallback) { mode = 'hash' } if (!inBrowser) { mode = 'abstract' } this.mode = mode switch (mode) { case 'history': this.history = new HTML5History(this, options.base) break case 'hash': this.history = new HashHistory(this, options.base, this.fallback) break case 'abstract': this.history = new AbstractHistory(this, options.base) break default: if (process.env.NODE_ENV !== 'production') { assert(false, `invalid mode: ${mode}`) } } }

构造器接收一个options参数

clipboard.png

默认mode为 "hash",如果显示传入参数mode为"history",则进行 是否支持的"history"的判断

this.fallback = mode === 'history' && !supportsPushState && options.fallback !== false

supportsPushState方法 里面 判断了 是否为浏览器环境且当前浏览器版本支持history

clipboard.png

options.fallback用来控制路由,在设置了mode为"history"但是当前浏览器环境不支持"history"的情况下是否应该回调判断,并重新设置mode为"hash"。

设置fallback为false本质上是为了让"router-link"在IE9上可以完整的页面刷新,如果是在hash模式下面不支持SSR,设置为false,会让那些在ie9服务端渲染的app更好用。(这段话没具体应用过)

clipboard.png

之后根据不同的mode,来执行不同的方案

clipboard.png

HTML5History

clipboard.png

构造器

构造器接收2个参数,router和base

router是在定义新路由的时候创建的对象
base如果没有传,则为undefined,
"?"这是通过一个名为flow的外部工具为javascript加上强类型检查的功能,不影响编译和运行。直接无视就好。
调动History的构造方法,History为 HTML5History,HashHistory,AbstractHistory的超类

clipboard.png

在History的构造方法中,

clipboard.png

如果base为undefined,查找是否有base的元素,有就赋值,没有就'/'

之后

const expectScroll = router.options.scrollBehavior    const supportsScroll = supportsPushState && expectScroll    if (supportsScroll) {      setupScroll()    }

判断路由参数,是否控制路由页面滚动条行为

clipboard.png

监听popstate事件,跳转

clipboard.png

clipboard.png

获取当前location的值之后,

clipboard.png

进行路由的更新,比如当前的History对应哪个路由

clipboard.png

clipboard.png

Html5History也添加了go,push,replace等方法用来路由跳转,

clipboard.png

先保存滚动条状态,之后可以使用history的自带方法进行地址的改变
clipboard.png

更多详情请见

未完待续

HashHistory

构造器

clipboard.png

调动History的构造方法,History为 HTML5History,HashHistory,AbstractHistory的超类
判断当前hash地址

clipboard.png

如果开头不是/#,将当前location按照hash格式化

clipboard.png

根据href获取当前hash,如果没有匹配到'#'返回空字符串。

初始化地址栏hash后

clipboard.png

clipboard.png

监听popstate事件,替换路由,控制滚动条行为

导航守卫

clipboard.png

在registerHook将设置的守卫入栈

在每次跳转的时候,递归守卫集合,将触发的守卫进行解析和执行。

clipboard.png

clipboard.png

AbstractHistory

构造器

clipboard.png

相对于上两种方法,AbstractHistory看起来要简单很多,这种模式是用于 Node.js 环境的,一般场景也就是在做测试的时候。但是在实际项目中其实还可以使用的,利用这种特性还是可以很方便的做很多事情的。(我没有用过)
因为不涉及和浏览器地址相关记录关联在一起;整体流程依旧和 HashHistory 是一样的,只是这里通过数组来模拟浏览器历史记录堆栈信息。

clipboard.png

更新历史堆栈信息,更新当前所处位置

等等,除了不使用浏览器的history对象,其他的和html5history模式差不多。

小结

vue-router的源码剖析到这里就结束了,大概流程是这个样子,得益于开发人员代码的简洁性及可读性,我们阅读起来障碍还是没有那么多,难度也没有那么大,整体逻辑不复杂,但是想要把很多不复杂的细节,整合到一起,认真到细节,才是程序设计的美学。

转载地址:http://btisx.baihongyu.com/

你可能感兴趣的文章
安卓中如何实现滑动导航
查看>>
Java-金额小数转换成中文大写金额
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
squid.3.2故障整理
查看>>
Ansible Tower安装配置全过程(上)
查看>>
地址与引用
查看>>
十大开源ERP点评 献给深水区的中小企业和CIO们
查看>>
【PHP】创蓝253云通信平台国际短信接口调用demo案例
查看>>
Confluence 6 重要缓存和监控
查看>>
Day 30 shell 编程
查看>>
静态路由和默认路由
查看>>
谈一谈Spring-Mybatis在多数据源配置上的坑
查看>>
2.1 shell语句
查看>>
【精益生产】车间现场管理的八大浪费
查看>>
springMVC国际化
查看>>
变频电源内部的元器件是有着什么样的发挥和作用
查看>>
关于阿里开发者招聘节 |这5道笔试真题 你会吗!???
查看>>
C#的异常处理机制
查看>>
写给MongoDB开发者的50条建议Tip13
查看>>