VueRouter原理深扒

2 篇文章 0 订阅
1 篇文章 0 订阅

VueRouter

vue-router是Vue.js框架的路由插件。
“更新视图但不重新请求页面” 是前端路由原理的核心之一。目前浏览器环境中这一功能的实现主要有两种方式。

  • 利用URL中的hash(“#”)
  • 利用History interface在HTML5中新增的方法。

创建VueRouter的实例对象时,mode以构造函数参数的形式传入。

  1. 作为参数传入的字符串属性mode只是一个标记,用来指示实际起作用的对象属性history的实现类,两者的对象关系为:
    history=>HTML5History,hash=>HashHistory,abstract=>AbstractHistory
  2. 在初始化history之前,会对mode做一些校验:若浏览器不支持HTML5History方式(通过supportsPushState变量来判断),则mode强制为“hash”;若不是在浏览器环境下运行,则mode强制为‘abstract
  3. VueRouter类中的onReady(),push()等方法只是一个代理,实际是调用的具体history对象的对应方法,在init()方法中初始化时,也是根据history对象具体的类别执行不同的操作

HashHistory
hash("#")符号的本来作用是加在URL中指示网页中的位置:

http://www.example.com/index.html#print

#符号本身以及它后面的字符称之为hash,可以通过window.location.hash属性读取。它具有如下特点:

  • hash虽然出现在url中,但不会被包括在http请求中。它是用来指导浏览器动作的,对服务器端完全无用,因此,改变hash不会重新载入页面。
  • 可以为hash的改变添加监听事件:
window.addEventListener("hashChange", funRef, false)
  • 每一次改变hash(window.location.hash),都会在浏览器的访问记录中增加一个新的记录。

利用hash的以上特点,就可以在前端实现“只更新视图不重新请求页面”的功能了。

HashHistory.push()
transitionTo()方法是父类中定义的用来处理路有变化基础逻辑的。
push()的方法最主要的是对windowhash对象进行了直接赋值。

window.location.hash = route.fullPath

hash的改变会自动添加到浏览器访问的历史记录中。
那么视图是怎么改变的呢??
当路由变化时候,调用了history中的this.cb方法,而this.cb方法是通过History.listen(cb)进行设置的。
回到VueRouter类定义中,在init()方法中对其进行设置。
通过Vue.mixin()方法,全局注册一个混合,影响注册之后每一个Vue实例,该混合在beforeCreated钩子中通过Vue.util.defineReactive()定义了响应式的_router属性。所谓响应式属性,即当_router值改变时,会自动调用Vue实例的render()方法,更新视图。
总结一下,从设置路由改变到更新视图的流程如下:

1.  $router.push() //调用方法
2.  HashHistory.push() //根据hash模式调用,设置hash并添加到浏览器历史记录中(添加到栈顶)(window.location.hash = XXX)
3.  History.transitionTo() //监测更新
4.  History.updateRoute() // 更新路由
5. {app._route = route} // 替换当前app路由
6.  vm.render() // 更新视图

HashHistory.replace()
replace()方法与push()方法的不同之处在于,它不是将新路由添加到浏览器访问历史的栈顶,而是替换掉当前的路由。
它与push()的实现结构基本相似,不同点在于它不是直接对window.location.hash进行赋值,而是调用window.location.replace方法将路由进行替换。

监听地址栏
用户还可以在浏览器地址栏中输入改变路由,所以VueRouter还需要监听地址栏中路由变化。在HashHistory中这一功能通过setListeners实现。
该方法设置监听了浏览器事件hashchange,调用的函数为replaceHash(),即在浏览器地址中直接输入路由相当于代码调用了replace()方法。

HTML5History:
History interface是浏览器历史记录栈提供的接口,通过back(),forword(),go()等方法,我们可以读取浏览器历史记录栈的信息,进行各种跳转工作。
HTML5开始,History interface提供了两个新的方法:pushState(), replaceState()使得我们可以对浏览器历史记录栈进行修改:

window.history.pushState(stateObject, title, URL);
window.history.replaceState(stateObject, title, URL);
  • stateObject:当浏览器跳转到新的状态时,将触发popState事件,该事件携带这个参数的副本
  • title:所添加记录的标题
  • URL:所添加记录的URL

这两个方法有个共同特点:当调用他们修改浏览器历史记录栈后,虽然当前URL改变了,但浏览器不会立即发送请求该URL。这就为单页面应用前端“更新视图但不重新请求页面”提供了基础。
代码结构中更新视图的逻辑与hash基本类似,只不过将对window.location.hash直接进行赋值window.location.replace()替换 变为调用 window.history.pushState()window.history.replaceState()
在HTML5History中添加对修改浏览器地址栏URL的监听是直接在构造函数中执行的。

两种模式比较:

  • pushState()设置新的URL可以是与当前URL同源的任意URL;而hash只可修改#后面的部分,故只可设置与当前同文档的URL。
  • pushState设置新的URL可以与当前URL一模一样,这样也会把记录添加到栈中。而hash设置的新值必须与原来不一样才会触发记录添加到栈中。
  • pushState通过stateObject可以添加任意类型的数据到记录中,而hash只可以添加短字符串。
  • pushState可以额外设置title属性供后续使用。
  • 如果用户直接在地址栏中输入并回车,浏览器重启重新加载应用。hash模式仅改变hash部分的内容,而hash部分是不会包含在http请求中的,所以hash模式下遇到更具URL请求页面的情况不会有问题。
    但是history模式会将URL修改的就和正常请求后端的URL一样,重新向后端发起请求,如果后端没有对应路由处理,就会返回404错误。 解决办法: 在服务端增加一个覆盖所有情况的候选资源,
  • 如果想在文件系统中直接加载Vue单页应用而不借助后端服务器,除了打包后一些路径设置外,还需要确保Vue-router使用的使hash模式。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值