PJAX是什么?

严格的说pjax是两个技术。

一、h5新增的history对象相关api,其中包含pushState方法和popstate事件。

二、是ajax数据

ajax加载可以数据,但是无法改变url。

因此有种方案是在内容发生改变后通过改变 URLhash 的方式获得更好的可访问性(如 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>

浏览器支持度

请输入图片描述

Last modification:October 7, 2020
如果觉得我的文章对你有用,请随意赞赏