history和路由

history浏览器历史和window.onpopstate

history

DOM window对象通过history对象提供了对浏览器历史的访问。它暴露了很多有用的方法和属性,允许你在用户浏览历史中向前和向后跳转,同时,从HTML5开始提供了对history栈中内容的操作。

History 对象是 window 对象的一部分,可通过 window.history 属性对其进行访问。

History对象属性

属性描述
length返回浏览器历史列表中的 URL 数量。
scrollRestoration允许Web应用程序在历史导航上显式地设置默认滚动恢复行为
state返回一个表示历史堆栈顶部的状态的值。这是一种可以不必等待popstate 事件而查看状态而的方式

History 对象方法

方法属性
back()加载 history 列表中的前一个 URL。
forward()加载 history 列表中的下一个 URL。
go()加载 history 列表中的某个具体页面。

History 对象最初设计来表示窗口的浏览历史。但出于隐私方面的原因,History 对象不再允许脚本访问已经访问过的实际 URL。唯一保持使用的功能只有 back()、forward() 和 go() 方法。

html5新特性:利用history的pushState等方法来解决使用ajax导致页面后退和前进的问题

使用ajax,可以实现不需要刷新整个页面就可以进行局部页面的更新。这样可以开发交互性很强的富客户端程序,减少网络传输的内容。但长期以来存在一个问题,就是无法利用浏览器本身提供的前进和后退按钮进行操作。比如在页面执行某个动作,该动作利用ajax请求到服务器获取数据,更新了当前页面的某些内容,这时想回到操作前的界面,用户就会习惯点击浏览器的后退按钮,实际这里是无效的。
HTML5引入了histtory.pushState()和history.replaceState()这两个方法,它们会更新history对象的内容。同时,结合window.onpostate事件,就可以解决这个问题。

方法属性
pushState()按指定的名称和URL(如果提供该参数)将数据push进会话历史栈
replaceState()按指定的数据,名称和URL(如果提供该参数),更新历史栈上最新的入口

pushState接受3个参数
1)第一个参数是个js对象,可以放任何的内容,可以在onpostate事件中获取到便于做相应的处理。

2)第二个参数是个字符串,目前任何浏览器都没有实现,但未来可能会用到,可以传个空串。

3)第三个参数是个字符串,就是保存到history中的url。
调用 pushState() 后浏览器并不会立即加载这个URL,但可能会在稍后某些情况下加载这个URL,比如在用户重新打开浏览器时。新URL不必须为绝对路径。如果新URL是相对路径,那么它将被作为相对于当前URL处理。新URL必须与当前URL同源,否则 pushState() 会抛出一个异常。该参数是可选的,缺省为当前URL。
pushState的作用是修改history历史,当调用方法时,将当前url存入history栈中,并在地址栏中显示参数中的url,但是并不会加载新的url。
replaceState的参数和pushState相同,但是调用时并不会将旧url存入history,而是将history中的url替换为参数中的url。

popstate事件在浏览器前进、后退时会触发,配合pushState和replaceState,可以解决使用ajax的页面前进后退的问题。具体解决方案是在触发ajax事件时同时调用pushState事件修改url信息,当popState 被触发时,同时调用history事件,根据当前url的不同,调用ajax事件恢复对应的状态。

history+popstate 应用:网页不是你想走,想走就能走

只需添加几行代码

这段代码会把当前url先加入url历史中,此时history栈顶端有两个相同的url,当点击后退事件时,退回到前一个url,但是页面会监听后退事件并再次push一个相同的url进入栈中。
对于用户来说点击后退按钮后,url永远不变,页面也没有重新加载(出于道德伦理公约,此方法慎用)

todo
popstate不是在哪个情况下都好用

chrome在考虑新的history实现
https://baijiahao.baidu.com/s?id=1633187248972482689&wfr=spider&for=pc

location

history是HTML5新方法,在旧版本的IE浏览器中有兼容性问题,并且history在更改url的时候不会发送请求刷新页面,
如果是想在切换url的同时加载url,则可以使用location.assign和location.replace方法

  • window.location.assign(url) : 加载 URL 指定的新的 HTML 文档。 就相当于一个链接,跳转到指定的url,当前页面会转为新页面内容,可以点击后退返回上一个页面。
  • window.location.replace(url) : 通过加载 URL 指定的文档来替换当前文档 ,这个方法是替换当前窗口页面,前后两个页面共用一个

history和location对比

优点:

  • 新的 URL 可以是与当前URL同源的任意URL 。而设置 window.location 仅当你只修改了哈希值时才保持同一个 document。
  • 如果需要,你可以不必改变URL。而设置 window.location = "#foo";在当前哈希不是 #foo 的情况下, 仅仅是新建了一个新的历史记录项。
  • 你可以为新的历史记录项关联任意数据。而基于哈希值的方式,则必须将所有相关数据编码到一个短字符串里。
  • 假如 标题 在之后会被浏览器用到,那么这个数据是可以被使用的(哈希则不然)。

缺点:

  • 如果用户直接在地址栏中输入并回车,浏览器重启重新加载等特殊情况。hash模式仅改变hash部分的内容,hash部分不会包含在http请求中,但history模式则将url修改的就和正常请求后端的url一样,
    后端没有配置对应的路由处理,会返回404错误。
  • 官方推荐的解决办法是在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。同时这么做以后,服务器就不再返回 404 错误页面,因为对于所有路径都会返回 index.html 文件。
    为了避免这种情况,在 Vue 应用里面覆盖所有的路由情况,然后在给出一个 404 页面。或者,如果是用 Node.js 作后台,可以使用服务端的路由来匹配 URL,当没有匹配到路由的时候返回 404,从而实现 fallback。

用history和location实现简单的路由

路由功能:

  • 点击按钮,url更新,通过执行js的方法切换页面
  • push方法把路由历史加入页面历史记录中,replace方法替换历史记录中的页面
  • 监听地址栏,用户手动输入路由时,显示对应内容
  • 分为hash模式和history模式

hash

history

使用

  1. 在初始化对应的history之前,会对mode做一些校验:若浏览器不支持HTML5History方式(通过supportsPushState变量判断),则mode设为hash;若不是在浏览器环境下运行,则mode设为abstract;
  2. VueRouter类中的onReady(),push()等方法只是一个代理,实际是调用的具体history对象的对应方法,在init()方法中初始化时,也是根据history对象具体的类别执行不同操作;

1-2 HashHistory
流程:

$router.push()-->HashHistory.push()-->History.transitionTo()-->History.updateRoute()-->{app._route=route}-->vm.render()

HashHistory.push()

HashHistory.replace()

1-3 transitionTo()

1-4 监听地址栏

1-5 HTML5History

popState监听地址栏变化

supportsPushState检查浏览器是否支持HTML5的history

评论 ( 0 )
最新评论
暂无评论

赶紧努力消灭 0 回复