资讯专栏INFORMATION COLUMN

(解析)单页应用路由实现没那么难--Vue

libxd / 2389人阅读

摘要:这段话没具体应用过之后根据不同的,来执行不同的方案构造器构造器接收个参数,和是在定义新路由的时候创建的对象如果没有传,则为,这是通过一个名为的外部工具为加上强类型检查的功能,不影响编译和运行。

前言

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

更新URL页面不刷新

监听URL的变化,执行页面替换逻辑

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

history.pushState等触发popstate事件

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参数

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

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

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

options.fallback用来控制路由,在设置了mode为"history"但是当前浏览器环境不支持"history"的情况下是否应该回调判断,并重新设置mode为"hash"。
设置fallback为false本质上是为了让"router-link"在IE9上可以完整的页面刷新,如果是在hash模式下面不支持SSR,设置为false,会让那些在ie9服务端渲染的app更好用。(这段话没具体应用过)

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

HTML5History

构造器

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

在History的构造方法中,

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

const expectScroll = router.options.scrollBehavior
    const supportsScroll = supportsPushState && expectScroll

    if (supportsScroll) {
      setupScroll()
    }

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

监听popstate事件,跳转


获取当前location的值之后,


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


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


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

更多详情请见MDN

未完待续

HashHistory 构造器


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

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

根据href获取当前hash,如果没有匹配到"#"返回空字符串。
初始化地址栏hash后

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

导航守卫

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

AbstractHistory 构造器


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

更新历史堆栈信息,更新当前所处位置
等等,除了不使用浏览器的history对象,其他的和html5history模式差不多。

小结

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/95668.html

相关文章

  • [使用 Weex 和 Vue 开发原生应用] 6 使用 vue-router

    摘要:使用值来作路由。原生应用本身就是多页的场景,页面间状态的隔离比共享更重要一些。使用开发的是原生应用,页面栈的管理使用的也是原生的特性,没有但是有模块可以实现页面的前进和后退等操作。 系列文章的目录在 ? 这里 (由于 我比较懒 最近一段时间在忙其他事,系列文章拖了好久终于又更新了。。。) 什么是 vue-router ? vue-router 官方文档 vue-router 是针对 V...

    leonardofed 评论0 收藏0
  • 单页应用的部署方案

    摘要:所以单页应用的部署,需要将所有的页面请求都返回,浏览器下载了后会自动解析并导航到对应页面。总结单页应用与以前的常规多页面应用还是有区别的,开发过程与后端解耦了,同时会出现跨域鉴权以及应用部署的问题。 本文同步发布于我的个人博客上 - 单页应用的部署方案 本文主要简单讲一下单页应用的开发及部署方法,默认你懂一些服务端知识及nginx知识,如果有任何可以在下方评论留言。 单页应用 SPA(...

    yanbingyun1990 评论0 收藏0
  • 前端路由简介以及vue-router实现原理

    摘要:后端路由简介路由这个概念最先是后端出现的。前端路由模式随着的流行,异步数据请求交互运行在不刷新浏览器的情况下进行。通过这些就能用另一种方式来实现前端路由了,但原理都是跟实现相同的。 后端路由简介 路由这个概念最先是后端出现的。在以前用模板引擎开发页面时,经常会看到这样 http://www.xxx.com/login 大致流程可以看成这样: 浏览器发出请求 服务器监听到80端口(或4...

    tuomao 评论0 收藏0
  • 面试官常问——vue

    摘要:如果要相应状态改变,通常最好使用计算属性或取而代之。那解决问题的思路便是在改变的情况下,保证页面的不刷新。后面值的变化,并不会导致浏览器向服务器发出请求,浏览器不发出请求,也就不会刷新页面。 1.vue生命周期2.vue 双向绑定原理3.vue router原理4.vue router动态路由 1.vue 生命周期钩子 showImg(https://segmentfault.com/...

    BlackMass 评论0 收藏0
  • 面试官常问——vue

    摘要:如果要相应状态改变,通常最好使用计算属性或取而代之。那解决问题的思路便是在改变的情况下,保证页面的不刷新。后面值的变化,并不会导致浏览器向服务器发出请求,浏览器不发出请求,也就不会刷新页面。 1.vue生命周期2.vue 双向绑定原理3.vue router原理4.vue router动态路由 1.vue 生命周期钩子 showImg(https://segmentfault.com/...

    xingqiba 评论0 收藏0

发表评论

0条评论

libxd

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<