路由的hash和history模式的区别

目录

[✅ 路由模式概述](#✅ 路由模式概述)

[一. 路由的hash和history模式的区别](#一. 路由的hash和history模式的区别)

[1. hash模式](#1. hash模式)

[2. history模式](#2. history模式)

[3. 两种模式对比](#3. 两种模式对比)

[二. 如何获取页面的hash变化](#二. 如何获取页面的hash变化)


✅ 路由模式概述

单页应用是在移动互联时代诞生的,它的目标是不刷新整体页面,通过地址栏中的变化来决定内容区域显示什么内容。

要达成这个目标,我们要用到前端路由技术,具体来说有两种方式来实现:hash模式和history模式。hash模式是通过监听hashChange事件来实现的,history模式是通过pushState方法+popstate事件来实现的。

一. 路由的hash和history模式的区别

Vue-Router有两种模式:hash模式和history模式。默认的路由模式是hash模式。

1. hash模式

◼️ 简介

hash模式(又称哈希路由)是开发中默认的模式,它的URL带着一个#,例如:http://www.abc.com/#/vue,它的hash值就是#/vue。

◼️ 特点

hash值会出现在URL里面,但是不会出现在HTTP请求中,对后端完全没有影响,所以改变hash值,不会重新加载页面。这种模式的浏览器支持度很好,低版本的IE浏览器也支持这种模式。 hash路由被称为是前端路由,已经成为SPA(单页面应用)的标配。

◼️ 原理

hash模式的主要原理就是onhashchange()事件:

javascript 复制代码
window.onhashchange = function(event){
	console.log(event.oldURL, event.newURL);
	let hash = location.hash.slice(1);
}

使用onhashchange()事件的好处就是,在页面的hash值发生变化时,无需向后端发起请求,window就可以监听事件的改变,并按规则加载相应的代码。 除此之外,hash值变化对应的URL都会被浏览器记录下来,这样浏览器就能实现页面的前进和后退。虽然是没有请求后端服务器,但是页面的hash值和对应的URL关联起来了。

hash模式是一种把前端路由的路径用 # 拼接在真实URL后面的模式。形式上,hash模式url里面永远带着#号,开发当中默认使用这个模式

原理是通过location.hash属性设置#后面的路径发生变化,并且浏览器并不会重新发起请求

只要hash地址发生改变,则会触发hashchange事件,我们在事件中设置地址对应的视图展示

hash模式的浏览器兼容性较好,就是看起来不够优雅。如果用户考虑url的规范,那么就需要使用history模式,因为history模式没有#号,是个正常的url,适合推广宣传;

2. history模式

◼️ 简介

history模式(又称历史路由)的URL中没有#,它使用的是传统的路由分发模式,即用户在输入一个URL时,服务器会接收这个请求,并解析这个URL,然后做出相应的逻辑处理。

◼️ 特点

当使用history模式时,URL就像这样:http://abc.com/user/id。相比hash模式更加好看。但是,history模式需要后台配置支持。如果后台没有正确配置,访问时会返回404。

history模式开发的SPA项目,需要服务器端做额外的配置,否则会出现刷新白屏(链接分享失效)。原因是页面刷新时,浏览器会向服务器真的发出对这个地址的请求,而这个文件资源又不存在,所以就报404。处理方式就由后端做一个保底映射:所有的请求全部拦截到index.html上。

◼️ API

history api可以分为两大部分,切换历史状态和修改历史状态:

**修改历史状态:**包括了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法,这两个方法应用于浏览器的历史记录栈,提供了对历史记录进行修改的功能。只是当他们进行修改时,虽然修改了url,但浏览器不会立即向后端发送请求。如果要做到改变url但又不刷新页面的效果,就需要前端用上这两个API。

切换历史状态: 包括forward()、back()、go()三个方法,对应浏览器的前进,后退,跳转操作。

虽然history模式丢弃了丑陋的#。但是,它也有自己的缺点,就是在刷新页面的时候,如果没有相应的路由或资源,就会刷出404来。 如果想要切换到history模式,就要进行以下配置(后端也要进行配置):

javascript 复制代码
const router = new VueRouter({
  mode: 'history',
  routes: [...]
})

history模式用到了HTML5中的history API,允许开发者直接更新浏览器URL地址而不重新发起请求。

用到了history API:replaceState、pushState、back、forward和go这个5个方法。

但是历史记录改变以后,视图并不会更新,我们需要在地址改变(包括使用onpopstate事件监听历史记录的回退)后,重新设置视图

history兼容性不如hash模式,而且浏览器在刷新的时候会按照路径发送真实的资源请求,因此在线上部署基于historyAPI的单页面应用的时候,一定要后端配合支持才行(如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面)

✅ 小 结:

👉🏻 两者原理不同

hash模式的实现原理是通过监听hashChange事件来实现的。

history模式是通过调用history.pushState方法(或者replaceState) 并且监听popstate事件来实现的。history.pushState会追加历史记录,并更换地址栏地址信息,但是页面不会刷新,需要手动调用地址变化之后的处理函数,并在处理函数内部决定跳转逻辑;监听popstate事件是为了响应浏览器的前进后退功能。

👉🏻 两者表现不同

hash模式会在地址栏中有#号,而history模式没有;同时由于history模式的实现原理用到H5的新特性,所以它对浏览器的兼容性有要求(IE >= 10)。

3. 两种模式对比

调用 history.pushState() 相比于直接修改 hash,存在以下优势:

  • pushState() 设置的新 URL 可以是与当前 URL 同源的任意 URL;而 hash 只可修改 # 后面的部分,因此只能设置与当前 URL 同文档的 URL;
  • pushState() 设置的新 URL 可以与当前 URL 一模一样,这样也会把记录添加到栈中;而 hash 设置的新值必须与原来不一样才会触发动作将记录添加到栈中;
  • pushState() 通过 stateObject 参数可以添加任意类型的数据到记录中;而 hash 只可添加短字符串;
  • pushState() 可额外设置 title 属性供后续使用。
  • hash模式下,仅hash符号之前的url会被包含在请求中,后端如果没有做到对路由的全覆盖,也不会返回404错误;history模式下,前端的url必须和实际向后端发起请求的url一致,如果没有对用的路由处理,将返回404错误。

hash模式和history模式都有各自的优势和缺陷,我们还是要根据实际情况选择性的使用。

二. 如何获取页面的hash变化

(1)监听$route的变化

javascript 复制代码
// 监听,当路由发生变化的时候执行
watch: {
  $route: {
    handler: function(val, oldVal){
      console.log(val);
    },
    // 深度观察监听
    deep: true
  }
},

(2)window.location.hash读取#值 window.location.hash 的值可读可写,读取来判断状态是否改变,写入时可以在不重载网页的前提下,添加一条历史访问记录。

参考资料vue路由和vue3总结

相关推荐
东风点点吹23 天前
HASH256开源代码计算错误问题
c语言·hash
程序猿-瑞瑞2 个月前
09 go语言(golang) - 数据类型:哈希表(map)及原理(一)
golang·散列表·hash
儒雅的烤地瓜3 个月前
JS | 如何解决ajax无法后退的问题?
前端·javascript·ajax·pushstate·popstate事件·replacestate
DieSnowK3 个月前
[Redis][Hash]详细讲解
redis·分布式·缓存·hash·使用场景·新手向·redis数据类型
安於宿命3 个月前
【C++进阶】hash表的封装
开发语言·c++·容器·hash
梦起丶3 个月前
Qt 中实现异步散列器
c++·qt·hash·qml
kidding7234 个月前
前端的面试题
前端·前端框架·vue-router·history·hash·abstract·v-bind
胜天半月子4 个月前
redis | 认识非关系型数据库Redis的哈希数据类型
redis·nosql·hash
wocwin4 个月前
解决Vue2移动端(H5)项目,手机打开项目侧滑或者按物理返回键,始终是走this.$router.go(-1)
vue.js·h5·history·移动端·popstate