文档章节

浅谈浏览器历史记录

放开那个女孩
 放开那个女孩
发布于 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/浅谈浏览器历史记录/

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

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

祈澈姑娘
2017/12/22
0
0
「前端」History API与浏览器历史堆栈管理

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

尚妆产品技术刊读
2017/03/01
0
0
浅谈MYSQL之日志文件系统

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

無言地对白
01/03
0
0
前端路由实现原理(history)

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

林晖
07/09
0
0
关于 HTTP GET/POST 请求参数长度最大值的一个理解误区

刚看到群里又有同学在说 HTTP 协议下的 Get 请求参数长度是有大小限制的,最大不能超过 XX,而 Post 是无限制的,看到这里,我想他们定是看多了一些以讹传讹的博客或者书籍, 导致一种理解上...

大数据之路
2013/06/09
0
3

没有更多内容

加载失败,请刷新页面

加载更多

下一页

JS三元运算示例

1. topFlag=topFlag ==0?1:0; 等于 if(topFlag=00){ topFlag=1; }else if(topFlag == 1){ topFlag=0; } 2. 5>3?alert('5大'):alert('3大'); 即 if(5>3){alert('5大')}else{alert('3大')}; 注......

森火
今天
0
0
利用Slf4j的MDC跟踪方法调用链

why? 一个web项目通常提供很多URL访问地址, 项目一般都是分层处理,例如Controller——>Service——>DAO。 如果想根据日志查看用户一次请求都走了哪些方法(多数是查错误)。 如果系统是多人...

杨春炼
今天
7
0
Maven介绍及安装

Maven介绍及安装 以下内容是本人早期学习时的笔记,可能比较详实繁琐,现在复习一下Maven,顺便将内容抛出来,供大家一起学习进步。 一、Maven简介 Maven是Apache旗下的一款项目管理工具,是...

星汉
今天
0
0
小程序Aes解密

主要步骤: 1、下载AES源码(JS版) 2、在小程序中新建一个公共的文件夹,把AES源码拷贝进去(注意:需要暴露接口 module.exports = CryptoJS;) 3、添加一个用于加密解密的公共JS,可取名为...

Mr_Tea伯奕
今天
0
0
Go实现文件传输(基本传输可用)

发送端 package mainimport ("fmt""os""net""io")func SendFile(path string, connect net.Conn){file, oerr :=os.Open(path)if oerr !=nil{fmt.Println("Open", oerr)......

CHONGCHEN
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部