vueRouter history模式和hash模式的区别

很长一段时间没有写博客了,换了个工作,就搁置了一段时间了,从今天开始,博客依旧会慢慢跟新,请大家多多支持。

前言

今天我们来谈谈vue 的路由vueRouter。我将会分2篇文章来带大家彻底理透vueRouter的原理。但要理解vueRouter,我们首先得了解vueRouter的两种模式
故,今天,我们先说说vueRouter的两种模式

  • history模式
  • hash模式

初步了解

我们大家都知道spa单页应用和传统前端之间一个很大区别就是spa单页应用可以在浏览器url地址发生变化时不向服务器发送请求的情况下更新我们的页面。

  • 传统应用改变页面视图的方式:
    • 传统前端应用改变页面视图的方式是通过从一个html跳转到领一个html实现的。当浏览去中url发生变化时,浏览器会根据url地址,向服务器去请求对应的html文件,然后浏览器再渲染拿到的html文件,从而更新页面。故这种方式,页面会闪一下
  • 路由改变页面视图的方式
    • 路由改变视图,主要靠的是vue 或者 react不刷新更新视图的原理。它会在浏览器url发生变化时,不再向服务端发送请求,而是通过一定的方式,找到所需要渲染的页面或组件,然后渲染这个页面或这个组件即可。从而实现这种效果的方式,主要有两种,history模式和hash模式(只针对vue)(这里插一句,不管哪种方式,底层最终实现页面无刷新更新视图的方式都是通过虚拟dom来实现的)

两种方式的对比

1、hash方式

  • hash方式是指url中存在 # 的一种方式,是vueRouter的默认模式,
  • 当#后面的url地址发生变化时,浏览器不会向服务器发送请求,故不会刷新页面
  • 当#后面的url地址发生变化时,会触发hashChange(hash模式得核心实现原理)事件,从而,我们可以通过监听hashChange事件来知道路由发生变化,从而进一步去更新我们的页面
  • 只可修改hash部分,
  • 当浏览器刷新时,浏览器只会向服务器去请求# 前面的域名服务器下根目录下的index.html文件
  • hash模式会创建hashHistory对象,hashHistory对象有两个方法,push() 和 replace()
    HashHistory.push()会将新的路由添加到浏览器访问的历史的栈顶,而HasHistory.replace()会替换到当前栈顶的路由

2、history模式

  • history模式得路由和域名之间直接通过/连接,无#符分隔,就是普通url形式
  • history模式当发生路由跳转时,通过HTML5的history.pushState()方法或者history.replaceState() 方法改变地址栏地址,并将地址的改变记录到浏览器访问栈中。(这里有一点需要注意,它只改变了浏览器地址栏中的地址,但并不会像服务器去发送请求)
  • 当浏览器前进,后台,或者调用back(),forward(), go()等方法时,会触发popstate事件。故,我们可以通过监听popstate事件来获取最新的路由地址,从而更新页面
  • 通过pushstate() 修改的url可以是与当前url同源的任意url。
  • 需要和服务器配合使用,否则容易出现页面404的情况

渲染过程对比

下面,我们来说说hash模式下和history下分别是如何一步步控制页面变化的。

在讲述过程之前,我们需要先来明白一个问题。不管是react,还是vue, 我们最终项目打包出来,大多只有一个index.html文件(除非是多入口打包)。故,web服务器上通常只会放一个index.html,其他都是js,css以及静态文件等

hash模式渲染过程

  1. 首先,当我们首次去访问一个hash模式的地址时,(假设访问地址为 www.xxx.com/#/about/dog) 那么,浏览器只会向地址为 www.xxx.com的web服务器的根目录下去请求index.html 文件。
  2. 解析index.html,发现有script标签引了对应的js文件,从而继续请求js文件
  3. 解析js文件,此时,在onload事件中,去根据当前路由地址,去路由映射表中查找对应的组件,然后router-view再渲染对应的组件,从而首次渲染出对应页面
  4. 当我们通过router-link去改变了路由地址时,首先会禁用a标签的href路径跳转,然后通过location.hash或者location.href去改变url中的地址为 #/xxx。
  5. 当url中地址一旦发生改变,会触发hashchange事件,在此事件中,去改变vue中一个用于存放当前url路由地址的变量的值 如:this.data.current = ‘/xxx’ ps:data是一个响应式数据,当current发生变化时,vue会监测到变化,从而所有依赖了current的地方都会进行更新
  6. current记录的url地址发生变化后,router-view内部是通过current的值,然后去路由映射表中查找对应的component,从而渲染对应的component。故router-view 是current的一个依赖着,故当current发生变化时,router-view会找到最新的url对应的component组件,从而渲染最新的组件。从而导致页面更新

history模式

  1. history模式,当浏览器首次访问某个地址时,或者以某个地址进行刷新浏览器时,浏览器会直接以当前地址去服务器中查找对应文件。如:当前url地址为 www.xxx.com/about/dog 时,如果刷新浏览器,那么浏览器会去 www.xxx.com这个web服务器的根目录下的about文件夹下的dog文件夹下去寻找index.html文件。但实际我们的index.html文件是存放在www.xxx.com这个服务器的根目录下的。所以此时,会找不到文件,浏览器就会报404的错误。这也是为什么history模式下时,需要和web服务器配合使用,需要web服务器在config文件下配置当找不到文件时,默认返回根目录下的index.html文件
  2. 浏览器拿到index.html文件后,解析html文件,发现scrpit引了js,请求js文件,解析js文件,在onload时,获取当前路由地址,去路由映射表中查找匹配的component组件,从而渲染对应组件
  3. 当通过router-link去改变了路由地址时,会调用history.pushState()方法去改变浏览器中的url地址,同时让this.data.current = 新的路由地址
  4. current的值一旦发生变化,会触发router-view去重新渲染当前路由地址对应的路由组件
  5. history模式下,当点击浏览器的前进,后退按钮时,只会去改变浏览器url中的路由地址,但是不会向服务器发送请求,同时,也不会去重新渲染页面
  6. 但是,浏览器点击前进,后退,会触发popstate事件,故,我们可以在popstate事件中,把当前最新的路由地址赋值给this.data.current ,current一旦发生变化,就会触发router-view组件重新渲染最新的路由组件(hash模式下,前进,后退一旦改变浏览器中的路由地址,就会自动触发hashchange事件,从而触发router-view的重新渲染)

好了,路由模式就介绍到这里了,有疑问欢迎私信或者下方评论。
后面,我会继续出一个vueRouter内部基础实现原理的文章。,感兴趣的可以看看

你可能感兴趣的:(vue,vue.js,javascript,vueRouter,history,hash)