KangKK

多读书,多运动,多到远处走走,再看看不一样的世界。

History

History对象

History对象是window对象的一部分,可通过window.history属性对其进行访问对浏览器历史记录的读取,内容为用户(在浏览器窗口中)访问过的URL。从HTML5开始,我们可以开始操作这个历史记录堆栈。

History对象属性

通过检查浏览器历史记录的length属性来找到历史记录堆栈中的页面总数。

属性 实例 描述
length var numberOfEntries = window.history.length; 返回浏览器历史列表中的URL数量

History对象方法

使用back(),forward(),和go()方法可以在用户的历史记录中前进和后退。

方法 实例 描述
back[1] window.history.back(); 加载history列表中的前一个URL
forward window.history.forward(); 加载history列表中的下一个URL
go[2] window.history.go(-1); 加载history列表中的某个具体页面

如果移动的位置超出了访问历史的边界,以上三个方法并不报错,而是默默的失败。

Manipulating the browser history

HTML5扩展Histroy

html5通过history.pushState等接口扩展了回退栈等功能。即所有的变化只发生在前端,这种方式下url变化,但实际上该url所对应的页面很可能不存在,url部分只作为回退栈的tag而存在。

方法 实例 描述
pushState history.pushState(data, title [, url]) 往历史记录堆栈顶部添加一条记录
replaceState history.replaceState(data, title [, url]) 修改浏览历史中当前纪录
参数 参数描述
data 一个与指定网址相关的状态对象,onpopstate事件触发时,该对象会传入回调函数。如果不需要这个对象,此处可以填null
title 新页面的标题,但是所有浏览器目前都忽略这个值,因此这里可以填null
url 新的网址,必须与当前页面处在同一个域。浏览器的地址栏将显示这个网址

通过pushState函数改变地址栏。

pushState

var stateObj = { foo: 'bar' };
history.pushState(stateObj, 'page 2', '2-page.html');

pushState

pushState方法不会触发页面刷新,只是导致history对象发生变化,地址栏会有反应。如果第三个参数url是带有http|https等网络协议标识的锚点,就要注意跨域问题。

history.pushState(null, null, 'https://img.baidu.com/hello');

pushState

不同源则报错。

history.pushState(null, null, 'https://www.baidu.com/hello');

pushState

使用how well does your browser support html5检查当前浏览器是否支持History API,不支持的话使用Benjamin Lupton等人写的Polyfill库(history.js)扩展history。

if (!!(window.history && history.pushState)){
  // 支持History API
} else {
  // 不支持
}

扩展使用window.history进行前端mvc跳转。

if (!!(window.history && history.pushState))
 {   
   // 支持History API
    var stateObj = { foo: "bar" };
    history.pushState(stateObj, "page 2", "user.html");
    // 监听出栈事件
    window.addEventListener(window,'popstate',function onPopStack(evt){
         var e = evt || window.event;
         console.log("location: " + document.location);   
         console.log("state: " + JSON.stringify(event.state));
         console.dir(evt);  
    },true);

 }
else {  
 // 不支持
}

pjax

        .--.
       /    \
      ## a  a
      (   '._)
       |'-- |
     _.\___/_   ___pjax___
   ."\> \Y/|<'.  '._.-'
  /  \ \_\/ /  '-' /
  | --'\_/|/ |   _/
  |___.-' |  |`'`
    |     |  |
    |    / './
   /__./` | |
      \   | |
       \  | |
       ;  | |
       /  | |
 jgs  |___\_.\_
      `-"--'---'

在现在追求用户体验的大环境下,主流网站都支持这样的一种浏览方式,当点击一个站内的链接的时候不做页面跳转,而是只是页面刷新变更地址栏目不变。页面变化内容是通过AJAX技术与后端进行交互,但是这样做有一个弊端,就是会破坏浏览器本身的回退功能,随着html5技术规范的推广,history.pushState的实现可以曲线解决这一问题。有人把pjax = pushState + ajax这种技术称之为pjax

其它

方法 参数描述
history.state 返回当前页面的state对象
window.onpopstate[3] 每当同一个文档的浏览历史(即history对象)出现变化时,就会触发popstate事件
URLSearchParams API[4] URLSearchParams API用于处理URL之中的查询字符串,即问号之后的部分。没有部署这个API的浏览器,可以用url-search-params这个垫片库

state

URLSearchParams有以下方法,用来操作某个参数。

方法 参数描述
has() 返回一个布尔值,表示是否具有某个参数
get()[5] 返回指定参数的第一个值
getAll() 返回一个数组,成员是指定参数的所有值
set() 设置指定参数
delete() 删除指定参数
append() 在查询字符串之中,追加一个键值对
toString() 返回整个查询字符串
keys() 遍历所有参数名
values() 遍历所有参数值
entries() 遍历所有参数的键值对
var paramsString = 'q=URLUtils.searchParams&topic=api';
var searchParams = new URLSearchParams(paramsString);
searchParams.has('topic');
==> true
searchParams.get('topic');
==> "api"
searchParams.getAll('topic');
==> ["api"]
searchParams.get('foo');
==> null
searchParams.set('foo', 2);
searchParams.get('foo');
==> "2"

兼容状况

桌面浏览器

Session history management ✔ 83.99% ◒ 7.31% [WHATWG Living Standard]
  Method of manipulating the user's browser's session history in JavaScript using `history.pushState`,
  `history.replaceState` and the `popstate` event. #HTML5

  IE ✘ 5.5+ ✔ 10+
  Edge ✔  
  Firefox ✘ 2+ ✔ 4+
  Chrome ✘ 4+ ✔ 5+
  Safari ✘ 3.1+ ◒ 5+ ✔ 6+
  Opera ✘ 9+ ✔ 11.5+

   ⓘ  Older iOS versions and Android 4.0.4 claim support, but implementation is too buggy to be useful.

移动浏览器

Session history management ✔ 83.99% ◒ 7.31% [WHATWG Living Standard]
  Method of manipulating the user's browser's session history in JavaScript using `history.pushState`,
  `history.replaceState` and the `popstate` event. #HTML5

  IE ✘ 5.5+ ✔ 10+
  Edge ✔  
  Firefox ✘ 2+ ✔ 4+
  Chrome ✘ 4+ ✔ 5+
  Safari ✘ 3.1+ ◒ 5+ ✔ 6+
  Opera ✘ 9+ ✔ 11.5+
  iOS Safari ✘ 3.2+ ◒ 4.2-4.3+ ✔ 5.0-5.1+
  Opera Mini ✘  
  Android Browser ✘ 2.1+ ✔ 2.2+ ✘ 3+ ✔ 4.2-4.3+
  Blackberry Browser ✔  
  Opera Mobile ✘ 10+ ✔ 11.1+
  Chrome for Android ✔  
  Firefox for Android ✔  
  IE Mobile ✔  
  UC Browser for Android ◒  
  Samsung Internet ✔  

   ⓘ  Older iOS versions and Android 4.0.4 claim support, but implementation is too buggy to be useful.

References