最近在自己博客网站添加音乐播放器后,发现切换页面会导致播放器的重新加载,不能保留之前的播放状态,为了解决这个问题,经过一番资料搜索,找到了pjax的解决方案。
pjax介绍
pjax = pushState + ajax 的缩写,它通过 ajax 和 pushState 技术提供了极速的(无刷新 ajax 加载)浏览体验,并且保持了真实的地址、网页标题,浏览器的后退(前进)按钮也可以正常使用。pjax 的工作原理是通过 ajax 从服务器端获取 HTML,在页面中用获取到的 HTML 替换指定容器元素中的内容。然后使用 pushState 技术更新浏览器地址栏中的当前地址。以下两点原因决定了 pjax 会有更快的浏览体验:
- 不存在页面资源(js/css)的重复加载和应用;
- 如果服务器端配置了 pjax,它可以只渲染页面局部内容,从而避免服务器渲染完整布局的额外开销。
history.pushState
history.pushState主要是在不刷新浏览器的情况下,创建新的浏览记录并插入浏览记录队列中。
1 | history.pushState(stateObject, title, url); |
- 状态对象(stateObject)– stateObject是一个JavaScript对象,通过pushState方法可以将stateObject内容传递到新页面中。
- 标题(title)– 几乎没有浏览器支持该参数,但是传一个空字符串会比较安全。
- 地址(url)– 新的历史记录条目的地址(可选,不指定的话则为文档当前URL);浏览器在调用pushState()方法后不会加载该地址;传入的URL与当前URL应该是同源的,否则,pushState()会抛出异常。
参考链接 https://www.cnblogs.com/sh-zj/p/9714467.html
其实 Vue 路径路由的实现也是用的此技术,有兴趣的可自行搜索研究。
Vue Router 路由实现原理 (https://www.cnblogs.com/gaosirs/p/10606266.html)
jquery-pjax
这里推荐一个jquery-pjax插件,大家可以去 https://github.com/defunkt/jquery-pjax 查看详细用法,下面主要介绍下常用操作。
在自己的网页中引入jquery和jquery-pjax脚本
1
2<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/jquery.pjax/2.0.1/jquery.pjax.min.js"></script>在html中准备替换的内容用div包裹起来,id自定义,类似如下:
1
2
3
4
5<body>
<div id="pjax-container">
<!-- 这里是准备pjax刷新替换的内容 -->
</div>
</body>接管网站所有a标签跳转, 注意我们这里不需要后台的话,记得一定要添加fragment指定为pjax容器。
1
2
3
4$(document).pjax('a[target!="_blank"]', '#pjax-container', {
fragment: "#pjax-container",
timeout: 5000
});对于简单的网站上面3步就已经够用了,但咱们的网站一般都会引入各种js, 所以最好我们开头就按需要,区别哪些是全局加载的,哪些是只需要局部刷新的,比如一般博客网址,header和footer部分都是不需要改变的,只需要变化中间部分等。可以参考以下代码结构:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37(function($){
var MyApp = {
initPjax: function(){
var self = this;
// 初始化
$(document).pjax('a[target!="_blank"]', '#pjax-container', {
fragment: "#pjax-container",
timeout: 5000
});
// pjax请求开始
$(document).on('pjax:start', function () {
});
// PJAX 渲染结束时
$(document).on('pjax:end', function() {
self.siteBootUp();
//在「局部刷新」时才会运行
console.log("局部执行");
});
self.siteBootUp();
},
/*
* Things to be execute when normal page load
* and pjax page load.
*/
siteBootUp: function(){
//「局部刷新」和「页面刷新」都需要运行的代码
console.log("全局执行");
}
};
window.MyApp = MyApp;
})(jQuery);
//「页面刷新」事件触发运行
$(document).ready(function() {
MyApp.initPjax();
});
博客适配pjax问题解决
以下记录本站博客兼容pjax时遇到的一系列问题解决。
博文搜索表单提交
一些表单提交操作的,pjax有两个事件要添加
1 | //表单提交事件 |
不蒜子计数统计
需要pjax请求完成后,重新加载的脚本,可以在pjax:complete之后重新load脚本
1 | $(document).on('pjax:complete', function () { |
Valine评论系统
初始化Valine时,记得参数中添加path参数,指定当前url路径,不然由于pjax的原因,valine会不刷新
1 | window.valine = new Valine({ |