利用pjax实现全站无刷新加载

正文索引 [隐藏]

我终于受不了我小破站上在跳转子页面的时候音乐播放器会刷新无法连续播放音乐的问题啦尴尬然后我向晚妹风向晚请教了这个问题,他让我去研究一下ajax这个技术,说是专门实现我这个需求的。

然后我开始研究Ajax,后来了解到还有Pjax….除了吃饭睡觉上课,我从昨天凌晨到现在将近一天半的时间里,我都在研究怎么实现网页的无刷新加载内伤这篇博客主要说一下,我在使用Pjax实现全站无刷新加载时踩的坑喷血我好傻比啊吐血倒地

关于AJAX:

AJAX 是 Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)的简称。它能在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页。ajax 是一种用于创建快速动态网页的技术。传统的网页(不使用 ajax)如果需要更新内容,必需重新加载整个网页。而AJAX通过在后台与服务器进行少量数据交换,可以使网页实现异步更新。这意味着ajax可以在不刷新整个网页的情况下,对网页的某部分进行更新加载。

关于PJAX:

pjax 是一个 jquery 插件,它通过 ajax 和 pushState 技术提供了极速的(无刷新 ajax 加载)浏览体验,并且保持了真实的地址、网页标题,浏览器的后退(前进)按钮也可以正常使用。
pjax 的工作原理是通过 ajax 从服务器端获取 HTML,在页面中用获取到的 HTML 替换指定容器元素中的内容。然后使用 pushState 技术更新浏览器地址栏中的当前地址。以下两点原因决定了 pjax 会有更快的浏览体验:①不存在页面资源(js/css)的重复加载和应用;②如果服务器端配置了 pjax,它可以只渲染页面局部内容,从而避免服务器渲染完整布局的额外开销

PJAX的使用:

先从github上下载jquery.pjax.js文件,下载链接:https://github.com/defunkt/jquery-pjax

然后看下github上的jquery-pjax官方文档给出的最简单的用法。

诶~看完之后,你肯定开始纳闷了,或许你还开始骂我了:只需要一行代码就可以实现全站pjax无刷新加载,你这个傻比居然研究了一天多?我…喷血我一开始也认为就一行代码这么简单,所以我在页脚footer.php里的代码是这样写的:

<script type='text/javascript' src='https://tanyaodan.com/wp-includes/js/jquery.pjax.js'></script>
<script>
    $(document).pjax('a[target!=_blank]', '#main', {fragment:'#main', timeout:8000});
</script>

先引入jquery.pjax.js文件,然后第二行js代码的意思是:对<div id=”main”></div>里面的所有不在新页面打开的a标签都使用pjax技术来进行加载。若ajax超时(8000ms),则在此之后强制对网页进行完全刷新。

这样音乐播放器就可以实现全站不间断播放了,但是我发现了第一个bug:站内搜索或者提交评论的时候,页面会完全刷新内伤继续浏览官方文档,可以找到解决方法。


照猫画虎锁眉下面这几行js代码可以实现评论和搜索等form提交事件时页面不完全刷新:

$(document).on('submit', 'form', function(event){
    $.pjax.submit(event, '#main',{fragment:'#main', timeout:8000});
});

然而!form提交事件会完全刷新页面这个bug解决之后,我又发现了一个引入pjax后而产生的新bug:js文件不会被重新载入而导致很多东西都没有js响应事件,比如代码高亮插件prism.js等,此时只需要重新载入js文件就好啦~观察亏得我还研究了半天pjax.reload。。。后来发现reload也没用,因为问题的根本原因是js文件没有重新载入。重新载入prism.js文件的代码如下(其它js文件的重新载入同理):

$(document).on('pjax:complete',function(){  //无论pjax的结果如何 超时与否 都触发
    if(typeof prism == 'undefined'){
        $.getScript("https://tanyaodan.com/wp-content/plugins/ah-prism-syntax-highlighter/js/prism.js");
    }
});

此时,愚蠢的我调用pjax的全部代码如下(PC端侧边栏还是有小bug、移动端菜单栏有点小bug)内伤

<script type='text/javascript' src='https://tanyaodan.com/wp-includes/js/jquery.pjax.js'></script>
<script>
    $(document).pjax('a[target!=_blank]', '#main', {fragment:'#main', timeout:8000}); 
    //评论和搜索等form提交事件无刷新
    $(document).on('submit', 'form', function(event){
        $.pjax.submit(event, '#main',{fragment:'#main', timeout:8000});
    });
    //post-content、代码框code-toolbar和评论区comment-part giligili-item局部重新刷新
    //重新加载js文件
$(document).on('pjax:complete',function(){
    if(typeof prism == 'undefined'){   //一个if就够了没必要每个js文件都判断
        $.getScript("https://tanyaodan.com/wp-content/plugins/ah-prism-syntax-highlighter/js/prism.js");
        $.getScript("https://tanyaodan.com/wp-content/themes/Giligili/js/app.js");
    }
});
</script>

2019年10月12日22:58更新~就不精确到秒啦~我终于好起来了,我太傻比了,我发现我的pjax-container写错啦,应该不是main而是main-part。写出下面的代码后,之前的bug全都解决了,切记不能直接getScript(app.js),得调用主题里面的函数即可。。。。。

最终代码:

<script type='text/javascript' src='https://tanyaodan.com/wp-includes/js/jquery.pjax.js'></script>
<script>
    $(document).pjax('a[target!=_blank]', '#main-part', {fragment:'#main-part', timeout:8000});
    $(document).on('submit', 'form', function(event){
        $.pjax.submit(event, '#main-part',{fragment:'#main-part', timeout:8000});
    });
    $(document).pjax('a:not(.post-type-link, .backstage, .no-pjax)[target!=_blank]', '#main-part', {fragment:'#main-part', timeout:8000});
    $(document).on('pjax:send', function() {
        $('#main-part').fadeTo(800,0.0);
    })
    $(document).on('pjax:complete', function() {
        $('#main-part').fadeTo(800,1);
        App.init();
        App.postType();
        App.postsPaging();
        App.commentsPaging();
        App.commentsSubmit();
        App.avatarAjax();
        App.codeHighLight();
        App.activatePower();
        App.photoBox();
        App.owoEmoji();
        if(typeof prism == 'undefined'){
            $.getScript("https://tanyaodan.com/wp-content/plugins/ah-prism-syntax-highlighter/js/prism.js");
        }
    })
    window.addEventListener('popstate',function(e) {
        $('#main-part').fadeTo(800,1);
        //alert('1');
        App.init();
        App.postType();
        App.postsPaging();
        App.commentsPaging();
        App.commentsSubmit();
        App.avatarAjax();
        App.codeHighLight();
        App.activatePower();
        App.photoBox();
        App.owoEmoji();
    }, false);
</script>