内容简介:众所周知,统一资源定位符(或称统一资源定位器/定位地址、URL地址等,英语:Uniform Resource Locator,常缩写为URL)标准格式:
众所周知, vue-router
有三种模式 : hash
、 html5
、 abstract
, 一般的前端项目中会选择 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 例子及它们的组成部分。
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
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
总结
- 标准的URL应该是 search + hash ,不要被当下各种框架欺骗,误以参数应该在hash后面拼接
- URL中可以有多个问号,但为了便于理解,还是尽量避免这种写法
- 避免上面尴尬问题的一个方法是 HTML5 Histroy 模式,感兴趣的同学可以关注并实践一下
- 了解原理,了解设计模式,可以借鉴到平时开发项目中
参考文档
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Building Websites with Joomla!
H Graf / Packt Publishing / 2006-01-20 / USD 44.99
This book is a fast paced tutorial to creating a website using Joomla!. If you've never used Joomla!, or even any web content management system before, then this book will walk you through each step i......一起来看看 《Building Websites with Joomla!》 这本书的介绍吧!