路由响应过程:
  1. 浏览器发出请求

  2. 服务器监听到num端口(或443)有请求过来,并解析url路径

  3. 根据服务器的路由配置,返回相应信息(可以是 html 字串,也可以是 json 数据,图片等)

  4. 浏览器根据数据包的 Content-Type 来决定如何解析数据

一般的vueRouter的代码模式是这样的:
let router = new Router({
mode: 'history|hash|abstract',
routes: [
{ // 默认页
path: '*',
redirect: to => {
return '/'
},
meta: {
status: ***
}
},
{
path: '/',
name: '****',
component: ****,
meta: {
status: ***
}
},
],
beforeEnter: (to, from, next) => {}),
scrollBehavior: fun()
})

可以看到的是使用Router这个类进行实例化【new Router(options)】

在使用vueRouter的时候,我们会在项目中使用Vue.use(Router)安装,它会加载VueRouter中的 install 方法使得所有组件都可以使用router的实例(this.$router/this.$route) 在install的时候实际上完成一些初始化的工作

(源码install.js)

1)在vue.prototype上注册一个$router/$route的实例

  Vue.mixin({
beforeCreate () {
if (isDef(this.$options.router)) {
this._routerRoot = this
this._router = this.$options.router Object.defineProperty(Vue.prototype, '$router', {
get () { return this._routerRoot._router }
}) Object.defineProperty(Vue.prototype, '$route', {
get () { return this._routerRoot._route }
})

2)全局注册RouterView, RouterLink这两个组件

 Vue.component('RouterView', View)
Vue.component('RouterLink', Link)
分为三种模式: hash, history(h5), abstract

(源码index.js)

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}`)
}
}
三种模式的简单描述:

a)hash

常见形式:http(https)://xxxxxx/#/xxxx

在h5之前浏览器不支持popState(window),pushState(history)和 replaceState(history)这几个事件,因此是通过hash值来改变路由,后面 hash 值的变化,并不会导致浏览器向服务器发出请求,浏览器不发出请求,也就不会刷新页面。另外每次 hash 值的变化,还会触发hashchange 这个事件,通过这个事件我们就可以知道 hash 值发生了哪些变化。然后我们便可以监听hashchange来实现更新页面部分内容的操作:

(源码hash.js)

 // supportsPushState用于用于判断浏览器是否支持h5
window.addEventListener(supportsPushState ? 'popstate' : 'hashchange', () => {
const current = this.current
if (!ensureSlash()) {
return
}
this.transitionTo(getHash(), route => {
if (supportsScroll) {
handleScroll(this.router, route, current, true)
}
if (!supportsPushState) { // 如果不支持pushState 就使用window.location.replace(getUrl(path))
      replaceHash(route.fullPath)
}
})
})

b)history

在h5之后,得到浏览器的支持就可以使用history模式了,在history模式下路由的改变会触发popstate事件,因此history模式原理也是对popstate事件的监听,然后做出相应操作。

(源码html5.js)

window.addEventListener('popstate', e => {
const current = this.current
// Avoiding first `popstate` event dispatched in some browsers but first
// history route not updated since async guard at the same time.
const location = getLocation(this.base)
if (this.current === START && location === initLocation) {
return
}
this.transitionTo(location, route => {
if (supportsScroll) {
handleScroll(router, route, current, true)
}
})
})

c)abstract

abstract 模式是用于原生开发(非浏览器typeof window=== 'undefined')的情况下,这就意味着不能使用window对象;另外由于在原生app中,页面储存一个数组栈中,它记录着页面的的访问记录,因此在js中最简单的就是定义数组进行模仿。

(源码abstrack.js)

constructor (router: Router, base: ?string) {
super(router, base)
this.stack = [] // 定义一个stack数组,用于存储路由
this.index = -1 // 记录每个路由在stack中的索引
}
关于popstate,pushState, replaceState:

1)window.popstate,history.pushState,history.replaceState是h5中新增的几个方法。

2)hash模式情况下路由的该变会触发window.hashtate,history模式下会触发window.popstate事件。

3)history.pushState()/replaceState() 会修改url ,不会使得页面更新,也不会触发window.popstate事件。

  在history模式下使得页面url与代码中路由地址相同

4)history.back() /go(),window.location.hash 都会使得页面改变,触发window.popstate事件。

  对此事件进行拦截处理一些事情(参数接收,页面位置记录)

    window.addEventListener(supportsPushState ? 'popstate' : 'hashchange', () => {
const current = this.current
if (!ensureSlash()) {
return
}
this.transitionTo(getHash(), route => {
if (supportsScroll) {
handleScroll(this.router, route, current, true)
}
if (!supportsPushState) {
replaceHash(route.fullPath)
}
})
})

5)使用导航的时候其实都是使用的 this.history.push()/ go() /replace() 进行页面切换。

  push (location: RawLocation, onComplete?: Function, onAbort?: Function) {
this.history.push(location, onComplete, onAbort)
} replace (location: RawLocation, onComplete?: Function, onAbort?: Function) {
this.history.replace(location, onComplete, onAbort)
} go (n: number) {
this.history.go(n)
}
back () {
this.go(-1)
}
forward () {
this.go(1)
}

  

https://segmentfault.com/a/1190000015123061

https://zhuanlan.zhihu.com/p/24574970

  

vue-router 结合源码分析原理的更多相关文章

  1. 从vue.js的源码分析,input和textarea上的v-model指令到底做了什么

    v-model是 vue.js 中用于在表单表单元素上创建双向数据绑定,它的本质只是一个语法糖,在单向数据绑定的基础上,增加了监听用户输入事件并更新数据的功能:对,它本质上只是一个语法糖,但到底是一个 ...

  2. koa2中间件koa和koa-compose源码分析原理(一)

    koa是基于nodejs平台的下一代web开发框架,它是使用generator和promise,koa的中间件是一系列generator函数的对象.当对象被请求过来的时候,会依次经过各个中间件进行处理 ...

  3. Vue.js 源码分析(七) 基础篇 侦听器 watch属性详解

    先来看看官网的介绍: 官网介绍的很好理解了,也就是监听一个数据的变化,当该数据变化时执行我们的watch方法,watch选项是一个对象,键为需要观察的数据名,值为一个表达式(函数),还可以是一个对象, ...

  4. 【转载】Android异步消息处理机制详解及源码分析

    PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbob ...

  5. vue双向绑定的原理及实现双向绑定MVVM源码分析

    vue双向绑定的原理及实现双向绑定MVVM源码分析 双向数据绑定的原理是:可以将对象的属性绑定到UI,具体的说,我们有一个对象,该对象有一个name属性,当我们给这个对象name属性赋新值的时候,新值 ...

  6. [Vue源码分析] v-model实现原理

    最近小组有个关于vue源码分析的分享会,提前准备一下… 前言:我们都知道使用v-model可以实现数据的双向绑定,及实现数据的变化驱动dom的更新,dom的更新影响数据的变化.那么v-model是怎么 ...

  7. Vue.js 源码分析(四) 基础篇 响应式原理 data属性

    官网对data属性的介绍如下: 意思就是:data保存着Vue实例里用到的数据,Vue会修改data里的每个属性的访问控制器属性,当访问每个属性时会访问对应的get方法,修改属性时会执行对应的set方 ...

  8. Vue.js 源码分析(二十七) 高级应用 异步组件 详解

    当我们的项目足够大,使用的组件就会很多,此时如果一次性加载所有的组件是比较花费时间的.一开始就把所有的组件都加载是没必要的一笔开销,此时可以用异步组件来优化一下. 异步组件简单的说就是只有等到在页面里 ...

  9. 前端Vue 源码分析-逻辑层

    Vue 源码分析-逻辑层 预期的效果: 监听input的输入,input在输入的时候,会触发 watch与computed函数,并且会更新原始的input的数值.所以直接跟input相关的处理就有3处 ...

随机推荐

  1. scrapy-redis基础和介绍

    一.scrapy-redis(0.6)依赖的环境 Scrapy >= 1.0.0                #终于过了1版本,这个太重要了,总算坑小了点,感谢那些为了解决各种scrapy与s ...

  2. zabbix项目实践

    一,Zabbix生产环境监测案例概述 1.1 项目规划 [x] :主机分组 交换机 Nginx Tomcat MySQL Apache PHP-fpm redis(也有状态页, 自己研究) memca ...

  3. Android 注解的使用与注意事项

    一般情况下我们最常用到的三个注解分别是@EActivity  @ViewById  和@Click    @EActivity这个注解是用来修饰Activity的,向Activity注入布局,功能相当 ...

  4. 团队项目之UML图设计

    团队 学号 姓名 本次作业博客链接 031602428 苏路明(组长) https://www.cnblogs.com/Sulumer/p/9822854.html 031602401 陈瀚霖 htt ...

  5. pdo::quey excu excute 区别

    PDO::query(PHP环境下同)和PDOStatement::execute函数均能实现SELECT查询功能,但官方文档并未见对此设计初衷的说明,此外还有个PDO::exec函数功能也很类似.天 ...

  6. jQuery Flipping Gallery 特效翻转画廊

    在线实例 简单配置 翻转方向 鼠标滚动 自动播放 绑定事件 使用方法 <div class="main"> <div class="page_conta ...

  7. kindle看扫描版pdf的解决办法

    (1)先把PDF crop (2)转JPEG (3)JPEG根据kindle的屏幕的分辨率,调整JPEG图像大小,kindle whater paper 大小为1448*1072 (4)   最后把j ...

  8. PyQt5编程:鼠标事件

    参考链接:https://www.cnblogs.com/zhuluqing/p/9028816.html 一.每个事件都被封装成相应的类: pyqt中,每个事件类型都被封装成相应的事件类,如鼠标事件 ...

  9. tesseract text2image windows

    text2image.exe --text="X:\xxx.txt" --outputbase="X:\test.font.exp0" --fontconfig ...

  10. HDU 1251:统计难题

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1251 题意不难理解,就是先输入不知道多少个字符串,然后用一个空行结束这个输入,然后接下来不知道多少行再 ...