美文网首页【vue-rouer源码】
【vue-router源码】五、router.addRoute、

【vue-router源码】五、router.addRoute、

作者: MAXLZ | 来源:发表于2022-06-07 10:44 被阅读0次

    前言

    【vue-router源码】系列文章将带你从0开始了解vue-router的具体实现。该系列文章源码参考vue-router v4.0.15
    源码地址:https://github.com/vuejs/router
    阅读该文章的前提是你最好了解vue-router的基本使用,如果你没有使用过的话,可通过vue-router官网学习下。

    该篇文章将分析router.addRouterouter.removeRouterouter.hasRouterouter.getRoutes的实现。

    使用

    • addRoute
      当使用addRoute添加路由时,如果第一个参数为路由name,那么会添加一个嵌套路由;否则添加的是个非嵌套路由。
    // 添加非嵌套路由
    router.addRoute({ name: 'admin', path: '/admin', component: Admin })
    // 添加嵌套路由
    router.addRoute('admin', { path: 'settings', component: AdminSettings })
    

    以上代码等同于:

    router.addRoute({
      name: 'admin',
      path: '/admin',
      component: Admin,
      children: [{ path: 'settings', component: AdminSettings }],
    })
    
    • removeRoute
    router.removeRoute('admin')
    
    • hasRoute
    router.hasRoute('admin')
    
    • getRoutes
    router.getRoutes()
    

    addRoute

    addRoute可接受两个参数:parentOrRoute(父路由的name或一个新的路由,如果是父路由的name,name第二个参数是必须的)、record(要添加的路由)。返回一个删除新增路由的函数。

    function addRoute(
        parentOrRoute: RouteRecordName | RouteRecordRaw,
        route?: RouteRecordRaw
      ) {
        let parent: Parameters<typeof matcher['addRoute']>[1] | undefined
        let record: RouteRecordRaw
        // 如果parentOrRoute是路由名称,parent为parentOrRoute对应的matcher,被添加的route是个嵌套路由
        if (isRouteName(parentOrRoute)) {
          parent = matcher.getRecordMatcher(parentOrRoute)
          record = route!
        } else { // 如果parentOrRoute不是路由名称,parentOrRoute就是要添加的路由
          record = parentOrRoute
        }
    
        // 调用matcher.addRoute添加新的记录,返回一个移除路由的函数
        return matcher.addRoute(record, parent)
      }
    

    在定义parent时,使用了一个Paramerer<Type>类型,对于该类型的使用可参考https://www.typescriptlang.org/docs/handbook/utility-types.html#parameterstype。在该方法中,parent的类型会取matcher.addRoute方法中的第2个参数的类型。

    isRouteName:通过判断name是否为stringsymbol类型,来决定是不是routeName

    export function isRouteName(name: any): name is RouteRecordName {
      return typeof name === 'string' || typeof name === 'symbol'
    }
    

    removeRoute

    删除路由。removeRoute接收一个name(现有路由的名称)参数。

    function removeRoute(name: RouteRecordName) {
      // 根据name获取对应的routeRecordMatcher
      const recordMatcher = matcher.getRecordMatcher(name)
      if (recordMatcher) {
        // 如果存在recordMatcher,调用matcher.removeRoute
        matcher.removeRoute(recordMatcher)
      } else if (__DEV__) {
        warn(`Cannot remove non-existent route "${String(name)}"`)
      }
    }
    

    hasRoute

    用于判断路由是否存在。hasRoute接收一个name字符串,返回一个boolen值。

    通过matcher.getRecordMatcher来获取对应的matcher,在matcher.getRecordMatcher会在matcherMap中取寻找对应的matcher,如果没有找到说明路由不存在。

    function hasRoute(name: RouteRecordName): boolean {
      return !!matcher.getRecordMatcher(name)
    }
    

    getRoutes

    获取标准化后的路由列表。标准化后的路由会被存储到matcher.record中。

    function getRoutes() {
      // 遍历matchers,routeMatcher.record中存储着路由的标准化版本
      return matcher.getRoutes().map(routeMatcher => routeMatcher.record)
    }
    

    总结

    router.addRouterouter.removeRouterouter.hasRouterouter.getRoutes几个API全都依赖matcher实现,可见matchervue-router的核心,如果你不了解matcher,建议回顾下之前的文章。

    相关文章

      网友评论

        本文标题:【vue-router源码】五、router.addRoute、

        本文链接:https://www.haomeiwen.com/subject/hffemrtx.html