vueRouter push问题的思考

背景

在开发vue的前端项目中,我们常常使用编程式路由来完成导航页面的切换。大家基本上都会使用到this.$router.push的方法。
常见的使用方法是:

this.$router.push({name:'a'});

this.$router.push({path:'/a'})

在项目的开发过程中,我使用了push方法采用上面的第二种方式,但是我书写的方式并没有带'/',我当时的路由假设为'/a',执行下面的方法,我的页面切换为'/b',这和我们一般书写的方式不一致,但是路径跳转是正常的。

this.$router.push({path:'b'})

研究阶段

我想知道path匹配的方式是带有'/'是从根路由开始替换的,但是如果我不带'/',为什么一切正常?我查询了官方文档,官方同样也有不带'/'的写法,但是并没有解释其中具体的逻辑。

于是我就去看了官方的源码。

顺着push方法一路找下去,我发现了一个方法utils/path.js有一个处理路径的方式:
resolvePath

export function resolvePath (
  relative: string,
  base: string,
  append?: boolean
): string {
  const firstChar = relative.charAt(0)
  if (firstChar === '/') {
    return relative
  }

  if (firstChar === '?' || firstChar === '#') {
    return base + relative
  }

  const stack = base.split('/')

  // remove trailing segment if:
  // - not appending
  // - appending to trailing slash (last segment is empty)
  if (!append || !stack[stack.length - 1]) {
    stack.pop()
  }

  // resolve relative path
  const segments = relative.replace(/^\//, '').split('/')
  for (let i = 0; i < segments.length; i++) {
    const segment = segments[i]
    if (segment === '..') {
      stack.pop()
    } else if (segment !== '.') {
      stack.push(segment)
    }
  }

  // ensure leading slash
  if (stack[0] !== '') {
    stack.unshift('')
  }

  return stack.join('/')
}

我传入的path路径在这里得到了解析,然后恢复正常了。
后来我在官方编写的测试用例中看到了这个方法的测试代码。

describe('Path utils', () => {
  describe('resolvePath', () => {
    it('absolute', () => {
      const path = resolvePath('/a', '/b')
      expect(path).toBe('/a')
    })

    it('relative', () => {
      const path = resolvePath('c/d', '/b')
      expect(path).toBe('/c/d')
    })

    it('relative with append', () => {
      const path = resolvePath('c/d', '/b', true)
      expect(path).toBe('/b/c/d')
    })

    it('relative parent', () => {
      const path = resolvePath('../d', '/a/b/c')
      expect(path).toBe('/a/d')
    })

    it('relative parent with append', () => {
      const path = resolvePath('../d', '/a/b/c', true)
      expect(path).toBe('/a/b/d')
    })

    it('relative query', () => {
      const path = resolvePath('?foo=bar', '/a/b')
      expect(path).toBe('/a/b?foo=bar')
    })

    it('relative hash', () => {
      const path = resolvePath('#hi', '/a/b')
      expect(path).toBe('/a/b#hi')
    })
  })
  ...
})

结合实际代码和测试用例我们发现:
当我们的原路径为/a,当我们push({path:b}),最终为生成'/b'
当我们的原路径为/a/c,当我们push({path:b}),最终为生成'/a/b'

当然还有其他各种情况,但是解决了我对于路径当前跳转的疑惑。大家有兴趣也可以试试别的方式。'../b'等方式,但是官方文档上并没有标出这些使用方式,所以大家还是尽量按照标准的方式。

希望可以解决大家对于官方文档上path前不带'/'的具体问题。

你可能感兴趣的:(前端vue.js)