最近在自己博客网站添加音乐播放器后,发现切换页面会导致播放器的重新加载,不能保留之前的播放状态,为了解决这个问题,经过一番资料搜索,找到了pjax的解决方案。
pjax介绍
pjax = pushState + ajax 的缩写,它通过 ajax 和 pushState 技术提供了极速的(无刷新 ajax 加载)浏览体验,并且保持了真实的地址、网页标题,浏览器的后退(前进)按钮也可以正常使用。pjax 的工作原理是通过 ajax 从服务器端获取 HTML,在页面中用获取到的 HTML 替换指定容器元素中的内容。然后使用 pushState 技术更新浏览器地址栏中的当前地址。以下两点原因决定了 pjax 会有更快的浏览体验:
- 不存在页面资源(js/css)的重复加载和应用;
- 如果服务器端配置了 pjax,它可以只渲染页面局部内容,从而避免服务器渲染完整布局的额外开销。
history.pushState
history.pushState主要是在不刷新浏览器的情况下,创建新的浏览记录并插入浏览记录队列中。
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脚本
<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自定义,类似如下:
<body> <div id="pjax-container"> <!-- 这里是准备pjax刷新替换的内容 --> </div> </body>
接管网站所有a标签跳转, 注意我们这里不需要后台的话,记得一定要添加fragment指定为pjax容器。
$(document).pjax('a[target!="_blank"]', '#pjax-container', { fragment: "#pjax-container", timeout: 5000 });
对于简单的网站上面3步就已经够用了,但咱们的网站一般都会引入各种js, 所以最好我们开头就按需要,区别哪些是全局加载的,哪些是只需要局部刷新的,比如一般博客网址,header和footer部分都是不需要改变的,只需要变化中间部分等。可以参考以下代码结构:
(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有两个事件要添加
//表单提交事件
$(document).on('submit', 'form', function (event) {
$.pjax.submit(event, '#pjax-container');
});
//表单提交成功事件
$(document).on('pjax:success', function (event) {
//console.log("关闭搜索框之类的操作");
});
不蒜子计数统计
需要pjax请求完成后,重新加载的脚本,可以在pjax:complete之后重新load脚本
$(document).on('pjax:complete', function () {
// 重新加载不蒜子
$.getScript('//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js');
});
Valine评论系统
初始化Valine时,记得参数中添加path参数,指定当前url路径,不然由于pjax的原因,valine会不刷新
window.valine = new Valine({
el:'#vcomment',
... //根据自己需要填写其他参数
recordIP: true,
path: window.location.pathname //[重点] 记得添加path路径
});
评论
能不用Jquery就不用Jquery吧
有大佬把jquery-pjax移植成了原生JavaScript
https://github.com/MoOx/pjax
用了pajx后,之前的一些jq效果也好好调整了一下,就是那个jq的each遍历老是报错,不知道是个什么原因。
非常感谢博主,解决了一个困扰了我半天的问题
我适配了pjax后,文章侧边栏自动打开有点问题,点击进文章页面时侧边栏不自动打开,要刷新一下。我看了一下源码,是传入1或者2控制的,大佬,你是咋个解决的啊?
出现了三个bug:
博主你好,我跟你使用的是同样的主题,也想用pjax优化一下博客,想问一下你具体更改了什么地方,感谢
👏棒棒哒