hash和hisitory的实现原理

        由于 Vuc 项目为单页面应用,所以整个项目在开发和构建过程中,仅存在一个 HTML物理文件。通过路由系统可以实现将项目的组件与可访问的 URL 路径进行绑定。由于 Vue项目只有一个 HTML 物理文件,切换页面时既需要让访问的 URL 路径发生变化,又不能触发HTML 物理文件的重新加载,这就使得 VueRouter 的跳页模式不能使用普通的超链接方式。
VueRouter 为了支持单页面应用的页面管理和页面跳转,提供了两种页面的跳转和加载模式:

(1)hash模式

        hash 模式使用了锚点技术重写URL访问路径,会在原有的 URL 路径后拼接/#/xxx,这种方式可以在不重新加载原有 HTML 文件的基础上,实现切换 URL 路径的目的。hash 模式的原理实现案例,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>hash模式的路由</title>
  <style>
    .page {
      width: 400px;
      height: 400px;
    }
    .about {
      background-color: antiquewhite;
      display: none;
    }
    .index {
      background-color: antiquewhite;
      display: none;
    }
  </style>
</head>
<body>
  <a href="#/index">访问首页</a>
  <a href="#/about">访问关于原页面</a>
  <div class="page index">
    我是首页
  </div>
  <div class="page about">
    我是关于页面
  </div>
  <script type="text/javascript">
    // url的hash部分切换事件
    window.onhashchange = function (event) {
      // 写两个的意思是跳转的时候新的显示,旧的隐藏
      // 获取要跳转的url路径并截取页面名称
      var newURL = event.newURL.split('#/')[1]
       // 获取跳转时的起点页面路径并截取页面名称
       var oldURL = event.oldURL.split('#/')[1]
      //  获取两个页面的dom对象
      var newPage = document.querySelector('.'+newURL)
      var oldPage = document.querySelector('.'+oldURL)
      // 显示目标页面
      newPage.style.display = 'block'
      // 隐藏当前页面
      oldPage.style.display = 'none'
    }
  </script>
</body>
</html>

        hash 模式利用了纯静态技术,解决了单页面应用的页面划分,它可以在不触发网页重新加载的情况下切换 URL路径,配合 onhashchange()可以实现,一旦 URL中的 hash 部分发生变化,就触发函数通知,通过 JavaScript 编程便可以很快速的实现 DOM 对象的切换展示。hash 模式同时也存在不足之处,如在分布式微前端项目中,嵌套的子应用和主应用都使用用hash 模式时,由于 hash 模式的 URL 路径只能存在一个#,会导致子应用和主应用在定义URL路上存在困难hash 模式的URL路径中包含#,也会在视觉上导致URL路径不美观。

注:分布式微前端:就是前端每个人写一个项目,他还是一个项目,网页要部署在不同的服务器上,用户访问的时候还感觉不出来。如果有多个项目互相合作使用hash模式,会导致#位置不一样,使项目配合出现问题。

       可以通过 给location.hash 赋值 改变 hash

location.hash = '/about'

     通过 a 标签,并设置 href 属性,当用户点击这个标签后,URL 的 hash 值会发生改变

<a href="#/hash">去hash页面</a>

     通过$router.push方法,会改变hash值触发hashchange事件,前进到指定的url

this.$router.push('/')

hash 路由模式的实现主要是基于下面几个特性:

  • URL 中 hash 值只是客户端的一种状态,也就是说当向服务器端发出请求时,hash 部分不会被发送;
  • hash 值的改变,都会在浏览器的访问历史中增加一个记录。因此我们能通过浏览器的回退、前进按钮控制hash 的切换;
  • 可以通过 a 标签,并设置 href 属性,当用户点击这个标签后,URL 的 hash 值会发生改变;或者使用  JavaScript 来对 loaction.hash 进行赋值,改变 URL 的 hash 值;
  • 我们可以使用 hashchange 事件来监听 hash 值的变化,从而对页面进行跳转(渲染)。

(2)history模式

       history 模式是 VueRouter 中常用的一种路由模式,它与 hash 模式不同,不需要借助错点技术重写URL路径,所以 history 模式使用的 URL 路径中不存在#,在视觉上更加美观, 利用H5的 history中新增的两个API pushState() 和 replaceState() 和一个事件onpopstate监听URL变化。               history 模式采用 history 对象中的 pushState()函数重写URL路径,可在触发重新加载的情况下变更URL路径,history 模式的原理,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>history模式</title>
  <style>
    .page {
      width: 400px;
      height: 400px;
    }
    .about {
      background-color: antiquewhite;
      display: none;
    }
    .index {
      background-color: antiquewhite;
      display: none;
    }
  </style>
</head>
<body>
  <!-- 定义路由菜单 -->
  <!-- 利用点击事件 -->
  <a href="javascript:jump('/index')">跳转到index页面</a>
  <a href="javascript:jump('/about')">跳转到about页面</a>
  <!-- 定义页面结构 -->
  <div class="page index">
    我是index页面
  </div>
  <div class="page about">
    我是about页面
  </div>
  <script type="text/javascript">
    // 跳转函数
    function jump(path){
      history.pushState(null,'page',path)
    // 获取所有页面组件
    var pages = document.querySelectorAll('.page')
    // 获取指定跳转的目标页面对象
    var newPage = document.querySelector(path.replace('/','.'))
    // 隐藏其他页面
    pages.forEach(item => item.style.display = 'none')
    // 展示跳转的页面
    newPage.style.display = 'block'
    }
  </script>
</body>
</html>

        history 模式重写 URL 路径的解决方案与 hash 式现象类似但本质不同,虽然 history模式可以重写URL路径,但是重写后的新路径中并不包含原有 HTML物理文件的访问地址,所以 history 模式在重写 URL 路径后,一旦刷新网页会造成404 无法访问的效果。VueCLI在开发环境中解决了 history 模式的刷新问题,不过项目发布到生产环境时,由于 history 模式的 URL路径问题,还需要配合生产服务器的转发规则重写,用以支持 history 模式的路由加载

        history.pushState() 和 history.repalceState()。这两个 API 可以在不进行刷新的情况下,操作浏览器的历史纪录。唯一不同的是,前者是新增一个历史记录,后者是直接替换当前的历史记录,如下所示:

window.history.pushState(null, null, path);  // 新增一个历史记录
window.history.replaceState(null, null, path); // 直接替换当前的历史记录
history.pushState(data, title, targetURL)

参数:

  • 状态对象:传给目标路由的信息,可为空
  • 页面标题:目前所有浏览器都不支持,填空字符串或者null即可
  • 可选url:目标url,不会检查url是否存在,且不能跨域。如不传该项,即给当前url添加data
window.history.replaceState(data, title, targetURL)
  • @类似于pushState,但是会直接替换掉当前url,而不会在history中留下记录

以这个链接为例       http://localhost:8080/#/

1、相同点

都不支持跨域

       

2、不同点

是否会留下记录

(1)history.pushState

可以用back 说明有留下记录。

(2)history.reloaceState

无法back,因为没有留下记录。

注:javascript 中的location.pathname

分析下面的URL: http://www.joymood.cn:8080/test.php?user=admin&pwd=admin#login

  • location.href:得到整个如上的完整url
  • location.protocol:得到传输协议   http:
  • location.host:得到主机名连同端口   www.joymood.cn:8080
  • location.hostname:得到主机名    www.joymood.cn
  • location.pathname:得到主机后部分不包括问号?后部分的   /test.php
  • location.search:得到url中问号?之后井号#之前的部分   ?user=admin&pwd=admin
  • location.hash:得到#及之后的部分   #login

“在 VueCLI项目中,可以通过 mode 属性来切换路由的 history 模式和 hash 模式。

在vue2中切换详解vue cli2.0路由的hash模式和history模式的打包并查看本地效果的方法-CSDN博客

在vue3中实现切换

vue3如何切换hash/history两种路由模式_vue3 路由模式-CSDN博客lianlian

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
哈希过滤器是一种常见的数据结构,它用于判断一个元素是否在一个集合中。它的主要原理是将元素映射到一个哈希表中的一个位置,如果该位置上已经有元素了,就说明该元素可能在集合中,否则该元素一定不在集合中。 具体来说,哈希过滤器包括两个主要部分:哈希函数和位图。 哈希函数将元素映射到哈希表中的一个位置,通常使用的是一些比较简单的函数,例如取模函数、乘法哈希函数、MurmurHash 等。 位图是一个二进制向量,它的每个元素都只能是0或1。哈希函数返回的值被用作位图中的下标,对应的位置上的值被设置为1,表示该元素存在于集合中。当判断一个元素是否在集合中时,只需要将它经过哈希函数得到的位置在位图中查找,如果该位置的值为1,则该元素可能在集合中,否则一定不在集合中。 以下是一个简单的基于 C 语言的哈希过滤器的实现示例: ```c #include <stdlib.h> #include <stdint.h> #include <stdbool.h> #define FILTER_SIZE 1000 typedef struct { uint8_t *bits; size_t size; } filter_t; filter_t *filter_create(size_t size) { filter_t *filter = (filter_t *)malloc(sizeof(filter_t)); filter->bits = (uint8_t *)calloc(size, sizeof(uint8_t)); filter->size = size; return filter; } void filter_add(filter_t *filter, const void *key, size_t len) { size_t index = *((size_t *)key) % filter->size; filter->bits[index] = 1; } bool filter_contains(filter_t *filter, const void *key, size_t len) { size_t index = *((size_t *)key) % filter->size; return filter->bits[index] == 1; } void filter_destroy(filter_t *filter) { free(filter->bits); free(filter); } ``` 该实现中,`filter_t` 结构体包含一个 `bits` 数组和 `size` 属性,其中 `bits` 数组用于存储位图,`size` 属性表示位图的大小。 `filter_create` 函数用于创建一个新的哈希过滤器,它接受一个参数 `size`,表示位图的大小。 `filter_add` 函数用于将一个元素添加到哈希过滤器中,它接受两个参数,`key` 和 `len`,分别表示要添加的元素和元素的长度。在该函数中,元素经过哈希函数得到一个下标 `index`,该下标对应的位置在位图中被设置为1,表示该元素存在于集合中。 `filter_contains` 函数用于判断一个元素是否在哈希过滤器中,它接
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值