vueRouter push問題的思考

背景

在開發vue的前端項目中,咱們經常使用編程式路由來完成導航頁面的切換。你們基本上都會使用到this.$router.push的方法。
常見的使用方法是:javascript

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

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

在項目的開發過程當中,我使用了push方法採用上面的第二種方式,可是我書寫的方式並無帶'/',我當時的路由假設爲'/a',執行下面的方法,個人頁面切換爲'/b',這和咱們通常書寫的方式不一致,可是路徑跳轉是正常的。前端

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

研究階段

我想知道path匹配的方式是帶有'/'是從根路由開始替換的,可是若是我不帶'/',爲何一切正常?我查詢了官方文檔,官方一樣也有不帶'/'的寫法,可是並無解釋其中具體的邏輯。vue

因而我就去看了官方的源碼。java

順着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路徑在這裏獲得瞭解析,而後恢復正常了。
後來我在官方編寫的測試用例中看到了這個方法的測試代碼。app

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'等方式,可是官方文檔上並無標出這些使用方式,因此你們仍是儘可能按照標準的方式。this

但願能夠解決你們對於官方文檔上path前不帶'/'的具體問題。code

相關文章
相關標籤/搜索