vue-router之history类浅析

栏目: JavaScript · 发布时间: 5年前

内容简介:当前版本: 3.0.3类目录: src/history/base.js对于vue-router来说,有三种路由模式history,hash,abstract, abstract是运行在没有window的环境下的,这三种模式都是继承于history类,history实现了一些共用的方法,对于一开始看vue-router源码来说,可以从这里开始看起。

当前版本: 3.0.3

类目录: src/history/base.js

前言:

对于vue-router来说,有三种路由模式history,hash,abstract, abstract是运行在没有window的环境下的,这三种模式都是继承于history类,history实现了一些共用的方法,对于一开始看vue-router源码来说,可以从这里开始看起。

初始属性

router: Router;  表示VueRouter实例。实例化History类时的第一个参数
  base: string;    表示基路径。会用normalizeBase进行规范化。实例化History类时的第二个参数。
  current: Route;  表示当前路由(route)。
  pending: ?Route; 描述阻塞状态。
  cb: (r: Route) => void;  监听时的回调函数。
  ready: boolean;  描述就绪状态。
  readyCbs: Array<Function>; 就绪状态的回调数组。
  readyErrorCbs: Array<Function>;  就绪时产生错误的回调数组。
  errorCbs: Array<Function>;  错误的回调数组

  // implemented by sub-classes
  <!-- 下面几个是需要子类实现的方法,这里就先不说了,之后写其他类实现的时候分析 -->
  +go: (n: number) => void;
  +push: (loc: RawLocation) => void;
  +replace: (loc: RawLocation) => void;
  +ensureURL: (push?: boolean) => void;
  +getCurrentLocation: () => string;

对于history类来说,主要是下下面两个函数的逻辑

transitionTo

这个方法主要是对路由跳转的封装, location接收的是HTML5History,HashHistory,AbstractHistory, onComplete是成功的回调,onAbort是失败的回调

transitionTo (location: RawLocation, onComplete?: Function, onAbort?: Function) {
    const route = this.router.match(location, this.current)  // 解析成每一个location需要的route
    this.confirmTransition(route, () => {
      this.updateRoute(route)
      onComplete && onComplete(route)
      this.ensureURL()

      // fire ready cbs once
      if (!this.ready) {
        this.ready = true
        this.readyCbs.forEach(cb => { cb(route) })
      }
    }, err => {
      if (onAbort) {
        onAbort(err)
      }
      if (err && !this.ready) {
        this.ready = true
        this.readyErrorCbs.forEach(cb => { cb(err) })
      }
    })
  }

confirmTransition

这是方法是确认跳转,route是匹配的路由对象, onComplete是匹配成功的回调, 是匹配失败的回调

confirmTransition(route: Route, onComplete: Function, onAbort?: Function) {
        const current = this.current
        const abort = err => {  // 异常处理函数
            if (isError(err)) {
                if (this.errorCbs.length) {
                    this.errorCbs.forEach(cb => { cb(err) })
                } else {
                    warn(false, 'uncaught error during route navigation:')
                    console.error(err)
                }
            }
            onAbort && onAbort(err)
        }
        if (
            isSameRoute(route, current) &&
            // in the case the route map has been dynamically appended to
            route.matched.length === current.matched.length
        ) {
            this.ensureURL()
            return abort()
        }
        <!-- 根据当前路由对象和匹配的路由:返回更新的路由、激活的路由、停用的路由 -->
        const {
            updated,
            deactivated,
            activated
        } = resolveQueue(this.current.matched, route.matched)
        <!-- 需要执行的任务队列 -->
        const queue: Array<?NavigationGuard> = [].concat(
            // beforeRouteLeave 钩子函数
            extractLeaveGuards(deactivated),
            // 全局的beforeHooks勾子
            this.router.beforeHooks,
            // beforeRouteUpdate 钩子函数调用
            extractUpdateHooks(updated),
            // config里的勾子
            activated.map(m => m.beforeEnter),
            // async components
            resolveAsyncComponents(activated)
        )
        
        this.pending = route
        <!-- 对于queue数组所执行的迭代器方法 -->
        const iterator = (hook: NavigationGuard, next) => {
            if (this.pending !== route) {
                return abort()
            }
            try {
                hook(route, current, (to: any) => {
                    if (to === false || isError(to)) {
                        // next(false) -> abort navigation, ensure current URL
                        this.ensureURL(true)
                        abort(to)
                    } else if (
                        typeof to === 'string' ||
                        (typeof to === 'object' && (
                            typeof to.path === 'string' ||
                            typeof to.name === 'string'
                        ))
                    ) {
                        // next('/') or next({ path: '/' }) -> redirect
                        abort()
                        if (typeof to === 'object' && to.replace) {
                            this.replace(to)
                        } else {
                            this.push(to)
                        }
                    } else {
                        // confirm transition and pass on the value
                        next(to)
                    }
                })
            } catch (e) {
                abort(e)
            }
        }
        
        runQueue(queue, iterator, () => {
            const postEnterCbs = []
            const isValid = () => this.current === route
            <!-- beforeRouteEnter 钩子函数调用 -->
            const enterGuards = extractEnterGuards(activated, postEnterCbs, isValid)
            const queue = enterGuards.concat(this.router.resolveHooks)
            <!-- 迭代运行queue -->
            runQueue(queue, iterator, () => {
                if (this.pending !== route) {
                    return abort()
                }
                this.pending = null
                onComplete(route)
                if (this.router.app) {
                    this.router.app.$nextTick(() => {
                        postEnterCbs.forEach(cb => { cb() })
                    })
                }
            })
        })
    }

结语:

每一次总结,都是对之前读源码的再一次深入的了解


以上所述就是小编给大家介绍的《vue-router之history类浅析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Code

Code

Charles Petzold / Microsoft Press / 2000-10-21 / USD 29.99

Paperback Edition What do flashlights, the British invasion, black cats, and seesaws have to do with computers? In CODE, they show us the ingenious ways we manipulate language and invent new means of ......一起来看看 《Code》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码