pjax实现音乐不间断播放

最近在自己博客网站添加音乐播放器后,发现切换页面会导致播放器的重新加载,不能保留之前的播放状态,为了解决这个问题,经过一番资料搜索,找到了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);
  1. 状态对象(stateObject)– stateObject是一个JavaScript对象,通过pushState方法可以将stateObject内容传递到新页面中。
  2. 标题(title)– 几乎没有浏览器支持该参数,但是传一个空字符串会比较安全。
  3. 地址(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 查看详细用法,下面主要介绍下常用操作。

  1. 在自己的网页中引入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>
  2. 在html中准备替换的内容用div包裹起来,id自定义,类似如下:

    1
    2
    3
    4
    5
    <body>
    <div id="pjax-container">
    <!-- 这里是准备pjax刷新替换的内容 -->
    </div>
    </body>
  3. 接管网站所有a标签跳转, 注意我们这里不需要后台的话,记得一定要添加fragment指定为pjax容器。

    1
    2
    3
    4
    $(document).pjax('a[target!="_blank"]', '#pjax-container', {
    fragment: "#pjax-container",
    timeout: 5000
    });
  4. 对于简单的网站上面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
2
3
4
5
6
7
8
//表单提交事件
$(document).on('submit', 'form', function (event) {
$.pjax.submit(event, '#pjax-container');
});
//表单提交成功事件
$(document).on('pjax:success', function (event) {
//console.log("关闭搜索框之类的操作");
});

不蒜子计数统计

需要pjax请求完成后,重新加载的脚本,可以在pjax:complete之后重新load脚本

1
2
3
4
$(document).on('pjax:complete', function () {
// 重新加载不蒜子
$.getScript('//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js');
});

Valine评论系统

初始化Valine时,记得参数中添加path参数,指定当前url路径,不然由于pjax的原因,valine会不刷新

1
2
3
4
5
6
window.valine = new Valine({
el:'#vcomment',
... //根据自己需要填写其他参数
recordIP: true,
path: window.location.pathname //[重点] 记得添加path路径
});
文章作者: Shawn
文章链接: https://www.shawnlin.cn/a54bd4f/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Shawn's Blog
打赏
  • 微信
  • 支付宝

评论