PJAX是什么?
严格的说pjax是两个技术。
一、h5新增的history对象相关api,其中包含pushState方法和popstate事件。
二、是ajax数据
ajax加载可以数据,但是无法改变url。
因此有种方案是在内容发生改变后通过改变 URL
的 hash
的方式获得更好的可访问性(如 https://liyu365.github.io/BG-UI/tpl/#page/desktop.html),但是 hash 的方式有时候不能很好的处理浏览器的前进、后退,而且常规代码要切换到这种方式还要做不少额外的处理。
history对象在h5中大大了增强、其中上述的方法就是弥补 ajax
中加载数据用浏览器回退页面重新加载的问题。
pjax
就是两个技术的结合体,是url hash解决方案的升级版本~!
什么是url的hash(#)
hash 属性是一个可读可写的字符串,该字符串是 URL 的锚部分(从 # 号开始的部分)
“#”
代表网页中的一个位置。其右面的字符,就是该位置的标识符
比如:
http://localhost/history.php#print
就代表网页index.html的print位置。浏览器读取这个URL后,会自动将print位置滚动至可视区域。
具体请参考:https://echo.solo90.com/archives/1151.html
pushSate方法
history.pushState(state, title[, url])
介绍
history.pushState()
方法向当前浏览器会话的历史堆栈中添加一个历史状态(state)。也就是在当前浏览器页面里面添加一条历史记录。
参数
state
可以是任何数据类型,Firefox将状态对象保存到用户的磁盘上,以便还原。数据最大640k,如果将序列化表示形式大于此状态的状态对象传递给 pushState()
,则该方法将引发异常。如果您需要更多空间,建议您使用 sessionStorage
或者localStorage
。
title
大多数浏览器忽略了此参数。
url
虽然是可选参数,如果用 pjax
那么这个url为必须参数。请注意,浏览器不会在调用 pushState()
之后尝试加载此URL,但可能会稍后尝试加载URL,例如在用户重新启动浏览器之后。 新的URL不必是绝对地址。 如果是相对的,则相对于当前URL进行解析。 新网址必须与当前网址相同 origin; 否则,pushState()
将引发异常。 如果未指定此参数,则将其设置为文档的当前URL。
例子
const state = { 'page_id': 1, 'user_id': 5 }
const title = ''
const url = 'hello-world.html'
history.pushState(state, title, url)
replaceState方法
history.replaceState(stateObj, title[, url]);
介绍
replaceState()
方法使用 state objects
, title
,和 URL
作为参数, 修改当前历史记录实体,如果你想更新当前的state对象或者当前历史实体的URL来响应用户的的动作的话这个方法将会非常有用。
参数
与pushState方法的参数一样
popstate事件
当活动历史记录条目更改时(也就是浏览器的前进和后退),将触发popstate事件。
如果被激活的历史记录条目是通过对 history.pushState()
的调用创建的,或者受到对 history.replaceState()
的调用的影响,popstate
事件的 state
属性包含历史条目的状态对象的副本。
使用demo
后端代码用PHP为例
index.php
<?php
$id=$_GET['page']."_".date('Y-m-d H:i:s')."_random=".$_GET['random'];
echo json_encode(['content'=>$id]);
history.php
点击链接两次可以看见记录
<?php echo date('Y-m-d H:i:s'); ?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="content">我是内容</div>
<a href="javascript:void(0);" class="aa" data-href="/index.php?page=up">上一页</a>
<a href="javascript:void(0);" class="aa" data-href="/index.php?page=down">下一页</a>
<div style="height:500px;"></div>
<div id="test" style="height:200px;background-color:orange"></div>
<div id="print" style="height:200px;background-color:bisque"></div>
<script src="./jquery.min.js"></script>
<script>
console.log(window.location.hash);
let a=document.getElementsByClassName('aa');
for (var i = 0; i < a.length; i++) {
a[i].addEventListener('click', function(e) {
var url=$(this).data('href')+"&random="+Math.floor(Math.random() * 10);
$.ajax({
url:url,
dataType:'JSON',
data:{},
type:"GET",
success:function(result){
var state={'uri':url,'title':url}
console.log(state);
$("#content").html(result.content);
state.content=result.content;
window.history.pushState(state,'url',url)
},
error:function(){
}
});
});
};
window.addEventListener('popstate', function(evt){
// console.log(history);
var state = evt.state;
if(state){
$("#content").html(state.content);
}
// console.log(state);
}, false);
</script>
</body>
</html>