文档章节

浅谈浏览器历史记录

放开那个女孩
 放开那个女孩
发布于 2017/08/28 14:26
字数 1434
阅读 9
收藏 0

为什么要研究浏览器历史记录,更加深入的了解单页面应有的路由

一、基本概念

  1. 浏览器历史记录管理栈
  2. 栈中的指针指向当前页面
  3. 如何生成一条历史记录
    1)点击页面中有a标签的href
    2)执行location.href = 'xxx'(location.replace('xxx')生成一条记录取代当前指针所指向的记录)
    3)表单提交跳转(注意只能跳到当前窗口)
    4)简单粗暴的方法,直接在当前页面的地址栏中输入地址
    5)使用pushState方法可以不刷新页面就可以生成一条历史记录,页面URL发生改变
    简言之,只要当页面的URL改变时,就会生成一条历史记录。在IE8及更高的版本中、Opera、Firefox、Chrome、Safari3及更高的版本中改变hash也会生成一条历史记录。
  4. 如何在浏览器中获取当前页面的历史记录状态
 

window.history

如下图所示

length:1 // 表示当前页面中会话历史元素的数目,当打开一个标签页时就会自动生成一个历史记录

scrollRestoration:"auto" // 允许web应用程序在历史导航上显示的设置默认滚动恢复行为。此属性可以是自动的(auto)或者是手动的(manual)。

这是一个实验的属性,在IE和Safari下不支持。

state:null // 返回一个表示历史堆栈顶部的状态的值。这是一种可以不必等待popstate事件而查看状态的方式。

指针指向的记录如果state不为null,则显示存进去的state。

history对象

二、浏览器对历史记录的管理策略

每次增添的历史记录都会在栈的最顶端,以谷歌浏览器为例
1)点击打开浏览器的标签页,此时生成一条历史记录,并打开测试页面进行测试。每打开一个页面都会生成一条历史记录,新历史记录压人栈顶。
测试的时候一定要在当前页打开页面。测试代码如下:

 

<div>

<a href="demo1.html">demo1</a>

</div>

<div>

<!--通过location.href="demo2.html"改变页面地址:-->

<button type="button" onclick="changTo(2);">href="demo2.html"</button>

</div>

<div>

<form action="demo3.html" method="get" class="dib"><button type="submit" >demo3.html</button></form>

</div>

<div>

<!--通过pushState来改变页面地址:-->

<button type="button" onclick="push4()">pushState"demo4.html"</button>

</div>

 

js代码如下:

 

function changTo(index) {

location.href = 'demo' + index + '.html';

}

function push4() {

history.pushState('hello', '', '/demo4.html')

}

 

点击demo1,demo2,demo3,demo4,然后再点击demo3,demo2,demo1生成的历史记录如下图
测试生成history对象

2)使用history API操作栈指针来获取历史页面

指针所在的位置会获取当前页面的state,
history.back() : 返回上一页
history.forword() : 跳转到前一页
history.go(n) : n可以为正数也可为负数,代表当前指针是向前移动还是向后移动几个位置。如果n大于或小于历史记录的数目时,指针不会发生任何变化。

下面图片的操作步骤为:先back() => go(-2) => go(-2) => go(2)
后退前进history指针变化

3)如果此时在demo3的位置点击demo1,历史记录栈会如下所示:
历史记录都是插入在栈指针所在位置的后面,前面的记录会被自动删除
后退前进history指针变化

4)历史记录超过了浏览器限制的最大条数(比如chrome、firfox为50条,IE超过了100),栈顶进入一条历史记录,则栈的底端移出去一条。

三、单页面应用中如何实现路由切换

目标:切换页面
异步传参

先介绍实现这种的两种方法:

HTML5推出的history API

三种方法:pushState replaceState onPopState

  1. pushState(state, title, URL)
    1). state: 代表一个Javascript对象,在创建对象的时候设置,可以在onpopstate和history对象中获取。(we impose a size limit of 640k characters on the serialized representation of a state object.)
    2). title: Firefox目前忽略这个参数,你可以给你的state设置一个小标题
    3). URL: 压人记录栈中URL,可选,不指定则视为当前URL。

    * 当执行pushState这个方法的时候不会去加载这个URL,但是会改变地址栏中的url。当重新加载这个页面时,URL是push进去的参数。
    * URL必须是同源链接
    
  2. replaceState(state, title, URL)参数和pushState一样,会替代当前指针指向的历史记录

  3. onPopState: 当指针在历史记录栈中已有的位置上移动时会触发,且指定的地址仍然在当前dom中。pushState和replaceState的操作不会触发这个事件
    MDN解释:

 

A popstate event is dispatched to the window every time the active history entry changes between two history entries for the same document.

The popstate event is only triggered by doing a browser action such as clicking on the back button (or calling history.back() in JavaScript).

And the event is only triggered when the user navigates between two history entries for the same document.

生成一条历史记录

1

window.history.pushState('{key: 1586}', '', '/demo1.html')

切换页面

1

2

3

4

window.addEventListener('popstate', e => {

const obj = e.state // 可获取栈指针指向的记录state

// dosometing

})warntext

异步传参

可根据state来传参

根据hash实现,hashchange来捕捉路由的变化

生成一条历史记录

 

getHash (): string {

// We can't use window.location.hash here because it's not

// consistent across browsers - Firefox will pre-decode it!

const href = window.location.href

const index = href.indexOf('#')

return index === -1 ? '' : href.slice(index + 1)

}

function pushHash (path) {

window.location.hash = path

}

function replaceHash (path) {

const i = window.location.href.indexOf('#')

window.location.replace(

window.location.href.slice(0, i >= 0 ? i : 0) + '#' + path

)

}

切换页面

hashchange监听后退和前进操作

1

2

3

window.addEventListener('hashchange',function(){

// dosometing

})

 

异步传参

1

2

3

4

5

6

7

8

9

10

11

12

13

14

function getParams(){

var hashArr = location.hash.split("?"),

hashName = hashArr[0].split("#")[1],//路由地址

params = hashArr[1] ? hashArr[1].split("&") : [],//参数内容

query = {};

for(var i = 0;i<params.length ; i++){

var item = params[i].split("=");

query[item[0]] = item[1]

}

return {

path:hashName,

query:query

}

}

本文转载自:https://x-front-team.github.io/2016/11/28/浅谈浏览器历史记录/

共有 人打赏支持
放开那个女孩
粉丝 3
博文 112
码字总数 43036
作品 0
杭州
程序员
浅谈移动端页面无刷新跳转问题的解决方案

浅谈移动端页面无刷新跳转问题的解决方案 2017-12-22 祈澈姑娘 最近开发微信公众号,用的框架是 一般的 UI,但是涉及到多页面之间的相互跳转的问题,降低了浏览器的性能,用户体验特别不好,...

祈澈姑娘
2017/12/22
0
0
目录帖:​​​​​​​浅谈算法和数据结构

浅谈算法和数据结构: 一 栈和队列 浅谈算法和数据结构: 二 基本排序算法 浅谈算法和数据结构: 三 合并排序 浅谈算法和数据结构: 四 快速排序 浅谈算法和数据结构: 五 优先级队列与堆排序 浅谈...

安小乐
09/04
0
0
浅谈MYSQL之日志文件系统

同大多数关系型数据库一样,日志文件是MySQL数据库的重要组成部分。MySQL有几种不同的日志文件,通常包括错误日志文件,二进制日志,通用日志,慢查询日志,等等。这些日志可以帮助我们定位m...

無言地对白
01/03
0
0
「前端」History API与浏览器历史堆栈管理

本文由尚妆前端开发工程师欲休撰写 本文发表于尚妆博客,欢迎订阅! 移动端开发在某些场景中有着特殊需求,如为了提高用户体验和加快响应速度,常常在部分工程采用SPA架构。传统的单页应用基...

尚妆产品技术刊读
2017/03/01
0
0
前端路由实现原理(history)

前端路由实现(history) 了解: HTML5 history新增了两个API:history.pushState和history.replaceState 两个api都接受三个参数 状态对象(state object):一个JavaScript对象,与用pushSta...

林晖
07/09
0
0

没有更多内容

加载失败,请刷新页面

加载更多

【大福利】极客时间专栏返现二维码大汇总

我已经购买了如下专栏,大家通过我的二维码你可以获得一定额度的返现! 然后,再给大家来个福利,只要你通过我的二维码购买,并且关注了【飞鱼说编程】公众号,可以加我微信或者私聊我,我再...

飞鱼说编程
今天
1
0
Spring5对比Spring3.2源码之容器的基本实现

最近看了《Spring源码深度解析》,该书是基于Spring3.2版本的,其中关于第二章容器的基本实现部分,目前spring5的实现方式已有较大改变。 Spring3.2的实现: public void testSimpleLoad(){...

Ilike_Java
今天
1
0
【王阳明心学语录】-001

1.“破山中贼易,破心中贼难。” 2.“夫万事万物之理不外于吾心。” 3.“心即理也。”“心外无理,心外无物,心外无事。” 4.“人心之得其正者即道心;道心之失其正者即人心。” 5.“无...

卯金刀GG
今天
2
0
OSChina 周三乱弹 —— 我们无法成为野兽

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @ _刚刚好: 霸王洗发水这波很骚 手机党少年们想听歌,请使劲儿戳(这里) hahahahahahh @嘻酱:居然忘了喝水。 让你喝可乐的话, 你准忘不了...

小小编辑
今天
11
0
vm GC 日志 配置及查看

-XX:+PrintGCDetails 打印 gc 日志 -XX:+PrintTenuringDistribution 监控晋升分布 -XX:+PrintGCTimeStamps 包含时间戳 -XX:+printGCDateStamps 包含时间 -Xloggc:<filename> 可以将数据保存为......

Canaan_
昨天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部