来自 软件资讯 2019-11-03 04:22 的文章
当前位置: 威尼斯国际官方网站 > 软件资讯 > 正文

浅谈history对象以致路由插件原理,单页应用

forward方法

forward方法可以加载历史列表中的下一个URL,类似于go(1),实现了点击浏览器前进按钮的效果。

window.history.forward()        // 前进
window.history.go(1)            // 前进
  • window.history
  • location.hash

简介

History对象最初设计用来表示窗口的浏览历史,但是,出于隐私方面的原因,History对象不再允许脚本访问已经访问过的实际URL。虽然,我们不清楚历史URL,但是,我们可以通过History对象的内置属性方法进行跳转。

源码分析VueVueRouter

HTML5新增方法

HTML5为History对象添加了两个新方法,pushStatereplaceState方法,用来在浏览历史中添加和修改记录。

1.Hash基本介绍

url 中可以带有一个 hash

window 对象中有一个事件是 onhashchange,以下几种情况都会触发这个事件:

  • 直接更改浏览器地址,在最后面增加或改变#hash;
  • 通过改变location.href或location.hash的值;
  • 通过触发点击带锚点的链接;
  • 浏览器前进后退可能导致hash的变化,前提是两个网页地址中的hash值不同。

back方法

back方法可以加载历史列表中的上一个URL,类似于go(-1),实现了点击浏览器后退按钮的效果。

window.history.back()           // 后退
window.history.go(-1)           // 后退

tips:当URL队列中没有上一个URL时,back方法会失效;同理,当URL队列中没有下一个URL时,forward方法会失效。

2.history.pushState

pushState(stateObj, title, url) 方法向历史栈中写入数据,其第一个参数是要写入的数据对象,第二个参数是页面的 title, 第三个参数是 url 。

  • stateObj :一个与指定网址相关的状态对象,popstate事件触发时,该对象会传入回调函数。如果不需要这个对象,此* 处可以填null。
  • title:新页面的标题,但是所有浏览器目前都忽略这个值,因此这里可以填null。
  • url:新的网址,必须与当前页面处在同一个域。浏览器的地址栏将显示这个网址。

关于pushState,有几个值得注意的地方:

  • pushState方法不会触发页面刷新,只是导致history对象发生变化,地址栏会有反应,只有当触发前进后退等事件和forward时浏览器才会刷新
  • 这里的 url 是受到同源策略限制的,防止恶意脚本模仿其他网站 url 用来欺骗用户,所以当违背同源策略时将会报错

replaceState方法

该方法基本和pushState一致,但是不同的是,该方法会直接替换当前的历史记录。

下面就来介绍下这两种方式具体怎么实现的

总结

虽然,history模式提供了完美的URL显示,但是,正所谓鱼和熊掌不可兼得,兼容性和美观也不可兼得。只有兼容了HTML5的浏览器(IE10+)才能使用history模式,不然,就老实的继续使用hash模式吧。

所以,使用何种模式,还是取决于软件的兼容性,如果不需要兼容低级浏览器,那就放心大胆的使用history模式吧!

3.history.replaceState

replaceState(stateObj, title, url) 和pushState的区别就在于它不是写入而是替换修改浏览历史中当前纪录,其余和 pushState一模一样。

pushState方法

pushState方法接收三个参数:

  • state:一个与指定网址相关的状态对象,popstate事件触发时,该对象会传入回调函数。如果不需要这个对象(即不需要传参),可以设为null
  • title:新页面的标题,但是大部分浏览器目前都忽略这个值,所以这里也可以设为null
  • url:新的网址,必须与当前页处在同一域,浏览器的地址栏将显示这个网址

比如当前的网址是localhost:63342/1.html,使用pushState方法在浏览记录中可以添加一条新的记录:

window.history.pushState({params: 'aaa'}, null, '2.html')

输入这行语句后,浏览器地址栏中的URL变为了localhost:63342/2.html,但是无论这是不是一个真实网址,它都不会跳转,这只是一条历史记录。此时,可以通过state取到状态。

此时,如果你前往下个地址后点击后退按钮,页面将返回到localhost:63342/2.html,此时,也可以通过state属性取到状态。

window.history.state            // {params: "aaa"}

tips:如果pushState的第三个参数是一个跨域网址,控制台会报错,这主要是因为安全问题,防止不法分子伪装URL

window.history.pushState(null, null, 'www.baidu.com')       // 报错

1.history基本介绍

window.history 对象包含浏览器的历史,window.history 对象在编写时可不使用 window 这个前缀。history是实现SPA前端路由是一种主流方法,它有几个原始方法:

  • history.back() - 与在浏览器点击后退按钮相同
  • history.forward() - 与在浏览器中点击按钮向前相同
  • history.go - 接受一个整数作为参数,移动到该整数指定的页面,比如go相当于forward相当于back相当于刷新当前页面
  • 如果移动的位置超出了访问历史的边界,以上三个方法并不报错,而是静默失败

在HTML5,history对象提出了 pushState() 方法和 replaceState() 方法,这两个方法可以用来向历史栈中添加数据,就好像 url 变化了一样(过去只有 url 变化历史栈才会变化),这样就可以很好的模拟浏览历史和前进后退了,现在的前端路由也是基于这个原理实现的。

length

该属性代表着浏览器历史列表中的URL数量。初始值为1,如果当前窗口先后访问了两个网址,那该属性的值变为2。

history.length          // 1
// 访问了一个新的URL
history.length          // 2

5.history实现spa前端路由代码

<a >abc.html</a><a >123.html</a><a href="/song" >song</a>

 // 注册路由 document.querySelectorAll.forEach(item => { item.addEventListener('click', e => { e.preventDefault(); let link = item.textContent; if (!!(window.history && history.pushState)) { // 支持History API window.history.pushState({name: 'history'}, link, link); } else { // 不支持,可使用一些Polyfill库来实现 } }, false) });//欢迎加入前端全栈开发交流圈一起学习交流:864305860 // 监听路由//面向1-3年前端人员 window.addEventListener('popstate', e => { console.log({//帮助突破技术瓶颈,提升思维能力 location: location.href, state: e.state }) }, false)//欢迎加入前端全栈开发交流圈一起学习交流:864305860

popstate监听函数里打印的e.state便是history.pushState()里传入的第一个参数,在这里即为{name: ‘history’}

本文由威尼斯国际官方网站发布于软件资讯,转载请注明出处:浅谈history对象以致路由插件原理,单页应用

关键词: