21.我想理解 hash history 两种前端路由

START

  • 番茄也写一写,前端路由的两种模式
  • 时间仓促,能力有限,难免有言语不当之处,望指正。

后端路由

  • 我最早接触路由这个概念呢,是在学习node.js的时候。使用node.js搭建一个后端服务,通过在后端服务配置不同的路由地址,浏览器请求这些地址。来获取各种内容(例如html,txt,json等).

    我眼中的路由呢,就好像是一种路径/地址,方便我们依据路径去寻找到对应的资源,仅此而已。

  • 早期的一些网站,就是用的后端路由,每点击一个菜单,就会切换一个url地址,来拿到不同的html以及其他资源展示出来。

    http://lazy_tomato/home          => 获取并展示home页面
    
    http://lazy_tomato/sayHello      => 获取并展示sayHello页面
    

总结一下

后端路由:每次切换url,会刷新页面,加载新的页面和资源。

前端路由

前端页面发展的历程

  1. 最初是后端把页面都处理好,直接返回给浏览器;
  2. 然后出现了ajax,页面上一部分交互是使用ajax去实时刷新的;
  3. 然后开始流行前端三大框架,然后开始流行单页面应用;

单页面应用(single page web application),简称SPA。

单页面应用,只有一个主页面,但是功能的切换,需要hash history 配合实现。

前端路由的工作方式

  1. 用户点击了页面上的路由链接;

  2. 导致了url地址栏中的值发生了变化,但是页面不会刷新(利用了hash history实现);

  3. 前端路由监听了地址的变化;

  4. 前端路由把当前地址对应的组件渲染都浏览器中;

本质上,其实就是浏览器的url变化,不刷新浏览器,切换页面展示。hash / history就可以实现我们这一要求。

1.hash

hash最明显的特点就是url中有一个#号。

例如:

https://www.baidu.com/#tomato

可以尝试一下啊,随便找个网址,在url最后面添加#和任意字符。发现在控制台的network中并不会加载数据和页面。

怎么获取url上的hash值?可以通过location.hash去获取

location.hash  // '#tomato'

怎么去监听hash的变化呢?

// 借助事件 `hashchange`
window.addEventListener('hashchange', event => {
  console.log(event)
})

测试截图如下:
在这里插入图片描述

2.history

除了hash模式,还有一种模式: history模式 ,它也可以改变url,但不刷新页面。

我们可以在浏览器中 使用 window.history 打印一下它。又或者去MDN官网查看一下history中包含那些属性和方法。

// 属性
history.length  // 表示会话历史中元素的数目,包括当前加载的页。
History.state   // 返回一个表示历史堆栈顶部的状态的值

// 方法
History.pushState()  // 按指定的名称和url(如果提供该参数)将数据push进会话历史栈。    简单理解添加一个路径。
History.replaceState() // 按指定的数据,名称和url(如果提供该参数),更新历史栈上最新的入口。

History.back()  // 返回一级
History.forward()  // 前进一级
history.go(-1)  // go(0)  刷新页面     正数=>前进几级; 负数=>后退几级; 如果超过边界,不报错也不执行。  

浏览器控制台上尝试一下这几个方法

表格可能看起来比较冗余,可以跳过这个表格,这个表格只是记录了一下我熟悉history上的方法时,运行的结果。

浏览器的url控制台输入命令输入命令后的url
https://www.baidu.com/history.pushState({},'','a1')https://www.baidu.com/a1
https://www.baidu.com/a1history.pushState({},'','a2')https://www.baidu.com/a2
https://www.baidu.com/a2history.pushState({},'','a3')https://www.baidu.com/a3
https://www.baidu.com/a3history.pushState({},'','a4')https://www.baidu.com/a4
https://www.baidu.com/a4history.back()https://www.baidu.com/a3
https://www.baidu.com/a3history.forward()https://www.baidu.com/a4
https://www.baidu.com/a4history.go(-2)https://www.baidu.com/a2
https://www.baidu.com/a2history.replaceState({},'','replacePage')https://www.baidu.com/replacePage
https://www.baidu.com/replacePagehistory.back()https://www.baidu.com/a1
https://www.baidu.com/a1history.forward()https://www.baidu.com/replacePage
https://www.baidu.com/replacePagehistory.forward()https://www.baidu.com/a3

怎么去监听history的变化呢?

window.onpopstate = function(){
   console.log(arguments)
}

运行截图
在这里插入图片描述

总结:

可以自己去浏览器打印一下这几个方法,其实就一个容器,然后通过自带的方法,加减历史记录栈,此处加减规则为先进后出

3.hash和history的相同点和不同点

相同点
  1. 都可以不刷新页面,切换url
不同点
  1. hash模式有#;history没有;

  2. hash 只可修改 url# 后面的部分;history 设置新url可以是与当前url同源的任意url;

  3. hash模式下出现在url#后面的部分,不会被包括在HTTP请求中,对后端没有影响,不会重新加载页面;history模式下,前端的url必须和实际向后端发起请求的url一致,若刷新页面,后端路由未处理,将返回404错误。

    如果是部署在nginx上的话,可以进行如下处理

    # 添加一个配置即可  try_files $uri $uri/ /index.html;
    # 1.记住不要找错配置文件; 2.不要忘记重启nginx。
    
    
    server {
         listen       80;
         server_name  localhost;
    
         #charset koi8-r;
    
         #access_log  logs/host.access.log  main;
    
         location / {
             root   html/dist;
             index  index.html index.htm;
    
             # !!针对 history模式的单页面应用,刷新404的问题
             try_files $uri $uri/ /index.html;
         }
    }
    
  4. hash只可添加短字符串;history通过pushState()第一个参数可以添加任意类型的数据到记录中;

vue-router源码解读

后续补充

END

  • 到这里基本上,路由两种模式都理解的很透彻了。
  • 作者:番茄
  • 编写时间:2022/04/28-20/24
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lazy_tomato

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值