轻易疏忽的URL

场景再现

尽人皆知,vue-router有三种形式 :hashhtml5abstract , 平常的前端项目中会挑选hash形式举行开辟,近来做了一个运营运动就是基于vue-router的hash形式举行开辟的。

  • 项目注册了两个路由(笼统出来的Demo)
var router = new VueRouter({
    routes: [{
        name: 'index',
        path: '',
        component: indexcomponent
    },{
        name: 'demo',
        path: '/demo',
        component: democomponent
    }]
});
  • 进口页面须要参数,所以供应URL:https://www.xxx.com?from=weixin, 浏览器里输入URL回车后,页面自动增添一个#/变成https://www.xxx.com?from=weixin#/
  • index页面中一个按钮点击后跳转demo,同时想照顾index中猎取的参数,看API挑选了以下体式格局,效果URL变成了:https://www.xxx.com?from=weixin#/test?userId=123
router.push({ 
    path: 'demo',
    query: { 
        plan: 'private'
    }
})

发生质疑

  • URL有什么规范?(上面Demo页面跳转后URL看起来怪怪的)
  • vue-router是怎样掌握URL的?

质疑探讨

URL规范

一致资本定位符(或称一致资本定位器/定位地点、URL地点等,英语:Uniform Resource Locator,常缩写为URL)

规范花样:scheme:[//authority]path[?query][#fragment]

==例子==

下图展现了两个 URI 例子及它们的组成部分。<!– 基于 RFC 3986 中的例子花样 –>
<pre style=”font-family:Courier,Courier New,DejaVu Sans Mono;monospace”>

                hierarchical part
    ┌───────────────────┴─────────────────────┐
                authority               path
    ┌───────────────┴───────────────┐┌───┴────┐

abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
└┬┘ └───────┬───────┘ └────┬────┘ └┬┘ └─────────┬─────────┘ └──┬──┘
scheme user information host port query fragment

urn:example:mammal:monotreme:echidna
└┬┘ └──────────────┬───────────────┘
scheme path</pre>

URL中的『?』『#』

  • 『?』

    • 途径与参数分隔符
    • 浏览器只辨认url中的第一个『?』,背面的会当作参数处置惩罚
  • 『#』

    • 『#』平常是页面内定位用的,如我们最熟习不过的锚点定位
    • 浏览器能够经由过程『onhashchange』监听hash的变化
    • http要求中不包括#
    • Request Headers中的Referer不包括#
    • 转变#不触发网页重载
    • url中#背面涌现的任何字符都会被截断。(http://www.xxx.com/?color=#fff发出要求是:/color=
    • 转变#会转变history
    • window.location.hash读取#值

URL读取和操纵

URL读取和操纵触及location和history两个对象,详细以下:

location API :

  • 属性

    • href = protocol + hostName + port + pathname + search + hash
    • host
    • origin
  • 要领

    • assign
    • href
    • replace ,不纪录history
    • reload

history API:

  • 要领

    • back()
    • forward()
    • go()
  • H5新增API

    • pushState()
    • replaceState()
    • popstate监听变化

vue-router路由完成浅析

初始化router的时刻,依据指定的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}`)
        }
}

我们挑选hash形式举行深入分析,对应HashHistory模块,该模块是history/hash.js完成的,当被挪用的时刻,对全局路由变化举行了监听

window.addEventListener(supportsPushState ? 'popstate' : 'hashchange', () => {
      ...
})

同时hash.js中也完成了push等api要领的封装,我们以push为例,依据源码能够看出,它的完成是基于基类transitionTo的完成,详细以下:

push (location: RawLocation, onComplete?: Function, onAbort?: Function) {
    const { current: fromRoute } = this
    this.transitionTo(location, route => {
      pushHash(route.fullPath)
      handleScroll(this.router, route, fromRoute, false)
      onComplete && onComplete(route)
    }, onAbort)
  }

既然挪用了transitionTo那末来看它的完成,猎取参数后挪用confirmTransition

transitionTo (location: RawLocation, onComplete?: Function, onAbort?: Function) {
    // 猎取URL中的参数
    const route = this.router.match(location, this.current)
    this.confirmTransition(route, () => {
      this.updateRoute(route)
      onComplete && onComplete(route)
      this.ensureURL()
      ...
    })
  }

同时confirmTransition里完成了一个行列,递次实行,iterator经由过程后实行next,进而志新pushHash(),完成页面hash转变,终究完成了${base}#${path}的衔接

function getUrl (path) {
  const href = window.location.href
  const i = href.indexOf('#')
  const base = i >= 0 ? href.slice(0, i) : href
  return `${base}#${path}`
}

function pushHash (path) {
  if (supportsPushState) {
    pushState(getUrl(path))
  } else {
    window.location.hash = path
  }
}

题目解决

  • https://www.xxx.com?from=weixin#/test?userId=123这个页面看起来觉得怪,是因为这个衔接中险些包括了一切的参数,而且hash内里另有一个问号,一个URL中多个问号的不常见
  • vue-router也是基于基础的URL操纵来举行URL切换的,在基础基础上举行了封装。内里许多思绪照样应当多进修自创的。比方完成的行列、继续的应用等

总结

  • 规范的URL应当是 search + hash ,不要被当下种种框架诳骗,误以参数应当在hash背面拼接
  • URL中能够有多个问号,但为了便于明白,照样只管防止这类写法
  • 防止上面为难题目的一个要领是 HTML5 Histroy 形式,感兴趣的同砚能够关注并实践一下
  • 相识道理,相识设想形式,能够自创到日常平凡开辟项目中

参考文档

    原文作者:keelvin
    原文地址: https://segmentfault.com/a/1190000015965899
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞