hash 模式

什么是 hash 模式

  1. 使用 window.location.hash 属性及窗口的 onhashchange 事件,可以实现监听浏览器地址 hash 值变化,执行相应的 js 切换网页:

    1. hash 指的是地址中 # 号 以及后面的字符,也称为 散列值hash 也称作锚点,本身是用来做页面跳转定位的,如 http://localhost/index.html#abc,这里的 #abc 就是 hash
    2. 散列值 是不会随请求发送到服务器端的,所以改变 hash ,不会重新加载页面;实际项目中地址栏只改变哈希部分,按下回车会向服务器发送请求,这个问题的出现是因为缓存的配置(强缓存,协商缓存),如果不配置任何缓存,地址栏没有任何变化,按下回车也会重新加载页面;
    3. 监听 hashchange 事件,可以当 散列值 改变时,通过 location.hash 来获取和设置 hash 值,location.hash 值的变化会直接反应到浏览器地址栏;
  2. 由于 hash 值变化不会导致浏览器向服务器发出请求,而且 hash 改变会触发 hashchange 事件,浏览器的进后退也能对其进行控制,所以 html5history 出现前,基本都是使用 hash 来实现前端路由的;

操作 hash

// 设置 url 的 hash,会在当前 url 后加上 '#qq'
window.location.hash = 'qq';

// 获取 hash 值,'#qq'  
window.location.hash 

// 监听 hash 变化,点击浏览器的前进后退会触发
window.addEventListener('hashchange', function(){ 
  // todo
})

触发 hashchange 事件的几种情况

  1. 第一种:浏览器地址栏 散列值 的变化(包括浏览器的前进、后退)会触发 window.location.hash 值的变化,从而触发 onhashchange 事件;

  2. 第二种:当浏览器地址栏中 URL 包含哈希如 http://www.baidu.com/#home ,这时按下输入,浏览器发送 http://www.baidu.com/ 请求至服务器,请求完毕之后设置散列值为 #home,进而触发 onhashchange 事件;

  3. 第三种:当只改变浏览器地址栏 URL哈希 部分,这时按下回车,浏览器不会发送任何请求至服务器,这时发生的只是设置散列值新修改的 哈希值 ,并触发 onhashchange 事件;

  4. 第四种htmla 标签的属性 href 可以设置为页面的元素 ID#top (锚点),当点击该链接时页面跳转至该 id 元素所在区域,同时浏览器自动设置 window.location.hash 属性,地址栏中的 哈希值 也会发生改变,并触发 onhashchange 事件;

history 模式

history 模式的由来

  1. hash 本来是拿来做页面定位的,如果拿来做路由的话,原来的锚点功能就不能用了;

  2. 其次 hash 的传参是基于 url 的,如果要传递复杂的数据,会有体积的限制,而 history 模式不仅可以在 url 里放参数,还可以将数据存放在一个特定的对象中;

  3. 最重要的一点:如果不想要很丑的 hash ,可以用路由的 history 模式;

history 概述

  1. window.history 属性指向 History 对象,它表示当前窗口的浏览历史,当发生改变时,只会改变页面的路径,不会刷新页面;

  2. History 对象保存了当前窗口访问过的所有页面网址,通过 history.length 可以得出当前窗口一共访问过几个网址;

  3. 由于安全原因,浏览器不允许脚本读取这些地址,但是允许在地址之间导航,浏览器工具栏的 前进后退 按钮,其实就是对 History 对象进行操作;

history 的 API 和属性

API、属性 描述
length 当前窗口访问过的网址数量(包括当前网页)
state History 堆栈最上层的状态值
back() 移动到上一个网址,等同于点击浏览器的后退键
forward() 移动到下一个网址,等同于点击浏览器的前进键
go(number) 接受一个整数作为参数,以当前网址为基准,移动到参数指定的网址;默认参数为 0 ,相当于刷新当前页面
pushState(object, title, url) 在历史中添加一条记录,不会触发页面刷新,只是导致 history 对象发生变化,地址栏会有变化
· object:通过 pushState 方法可以将该对象内容传递到新页面中
· title:几乎没有浏览器支持该参数,传一个空字符串比较安全
· url:新的网址,必须与当前页面处在同一个域,不指定的话则为当前的路径,如果设置了跨域网址,则会报错
replaceState(object, title, url) 替换的当前记录,而不是添加一条新的记录

popstate 事件

  1. 每当 history 对象出现变化时,就会触发 popstate 事件

    1. 仅仅调用 pushState()replaceState() 方法 ,并不会触发该事件;
    2. 只有用户点击浏览器倒退按钮和前进按钮,或者使用 JavaScript 调用 History.back()History.forward()History.go() 时才会触发;
    3. 另外,该事件只针对同一个文档,如果浏览历史的切换,导致加载不同的文档,该事件也不会触发;
    4. 页面 第一次加载 的时候,浏览器不会触发 popstate 事件;
  2. 使用的时候,可以为 popstate 事件指定回调函数,回调函数的参数是一个 event 事件对象,它的 state 属性指向当前的 state 对象:

    window.addEventListener('popstate', function(e) {
      // e.state 相当于 history.state
      console.log(history.state);
    });
    

history 模式需要后端支持

  1. history 模式要玩好,还需要后端配置支持,因为应用是个单页客户端应用,仅有一个入口文件就是 index.html,浏览器直接访问 http://oursite.com/index.html 可以正常加载应用,此时在应用上面做操作完全没有问题,因为不会向后端发送请求;

  2. 当发生了下面两种情况,后端会因为 url 不匹配而报错:

    1. 客户 ctrl + F5 刷新页面,或者地址栏按 enter 键重新加载页面,恰好此时页面的 url 不是 http://oursite.com/index.html
    2. 客户不是通过 http://oursite.com/index.html 访问页面,而是通过 http://oursite.com/dashoard 访问页面;
  3. 对浏览器和后端来说,history 模式的 url 就是正常的 url,后端会根据匹配规则匹配相应的 api 接口 或者 静态资源 ,因此需要在后端添加一个匹配所有情况的配置,如果 url 匹配不到,就返回 index.html 页面;

打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. hash 模式
    1. 1.1. 什么是 hash 模式
    2. 1.2. 操作 hash
    3. 1.3. 触发 hashchange 事件的几种情况
  2. 2. history 模式
    1. 2.1. history 模式的由来
    2. 2.2. history 概述
    3. 2.3. history 的 API 和属性
    4. 2.4. popstate 事件
    5. 2.5. history 模式需要后端支持