这应该是Typecho上最简单的使用PJAX的方案了
MoOx/Pjax 官方说明
轻松在任何网站上启用快速的AJAX导航(使用pushState() + XHR)
MoOx/Pjax(以下简称Pjax)是一个独立的JavaScript模块,使用AJAX(XmlHttpRequest)和pushState()来提供快速的浏览体验。
Pjax库方便你改善传统网站(服务端渲染的或者静态网站)的用户体验,使用户感觉像在使用应用程序,尤其是那些宽带质量差的用户。
不再需要完整的页面重新加载。不会创建多个HTTP请求。
Pjax不依赖于其他库,如jQuery或类似的库,完全使用原生JS编写。
需要具备基础的html & javascript 知识。如果你连div和script标签仍然不认识,请忽略该篇文章。
初步改造
1.引入 JS(这里采用国内的CDN),建议修改footer.php引入,在</body>之前插入即可
<script src="https://jsd.onmicrosoft.cn//npm/pjax@0.2.8/pjax.min.js"></script>
<script>
    document.addEventListener('pjax:send', () => {
        NProgress.start();
    });
    document.addEventListener('pjax:complete', () => {
        NProgress.done();
    });
    let pjax = new Pjax({
        elements: 'a[href^="<?php $this->options->siteUrl(); ?>"]:not(a[target="_blank"], a[no-pjax], a[href^="<?php $this->options->adminUrl(); ?>"])',
        selectors: [
            "title",
            ".main-menu",
            "main",
            "#logout",
        ]
    });
    // 这里插入其他代码
</script>注意这里要修改selectors,selectors是告诉脚本 Pjax 加载的新页面那些部分的内容要替换到网页上,格式为css选择器。比如title是网页标题;比如退出链接,我给加了个IDlogout,所以是#logout,如果导航菜单做了高亮当前也也是需要替换的,至于正文内容就更不用说了。
加载动画
加载动画是让用户有网页正在加载的感觉,推荐使用NProgress,或者你自己写也行。反正我用的是 Nprogress。
1.引入 Nprogress,放在 Pjax 脚本之前
<link href="https://cdn.bootcdn.net/ajax/libs/nprogress/0.2.0/nprogress.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/nprogress/0.2.0/nprogress.min.js"></script>2.然后在 Pjax 初始化脚本之后插入
document.addEventListener('pjax:send', () => {
    NProgress.start();
});
document.addEventListener('pjax:complete', () => {
    NProgress.done();
});pjax:send是pjax刚开始发送网络请求时触发的事件pjax:complete是pjax完成后触发的事件
如果是使用自定义动画,请将NProgress.start()和NProgress.done()替换为自己的代码
修复一些问题问题
1.开启了 Pjax 之后发现表情无法加载了,回到顶部不换用啦,Lazyload不加载图片啦,点赞弹窗不可用啦等等的问题都是因为Pjax只是替换部分页面内容,JS 那些还是原来老的,只能在PJAX完成的时候触发一下重载事件。
document.addEventListener('pjax:complete', () => {
    NProgress.done();
    new OwO(); // 重新初始化表情
    GoTop.init(); // 回到顶部重载
    LayzloadInstance.update() // Lazyload 重载
});2.开启Pjax可以评论无法回复
我观察了一下,是因为 Typecho 默认输出的 评论 JS 是写死 comment-id 的,只能屏蔽原来的 JS 脚本,改成自动获取 ID的。
修改header.php把$this->header()修改为$this->header('commentReply='),这样就可以屏蔽原来的输出。
Header 其他参数参见
屏蔽了评论 JS 输出就会导致无法评论,所以得增加修改版的评论JS,插入到 PJAX 初始化脚本后面即可(就
// 这里插入其他代码那里)window.TypechoComment = {
    dom: function (id) {
        return document.getElementById(id);
    },
    query: function (sel) {
        return document.querySelector(sel);
    },
    create: function (tag, attr) {
        var el = document.createElement(tag);
        for (var key in attr) {
            el.setAttribute(key, attr[key]);
        }
        return el;
    },
    reply: function (cid, coid) {
        var comment = this.dom(cid), parent = comment.parentNode,
            response = this.query(".comment-respond"), input = this.dom('comment-parent'),
            form = 'form' == response.tagName ? response : response.getElementsByTagName('form')[0],
            textarea = response.getElementsByTagName('textarea')[0];
        if (null == input) {
            input = this.create('input', {
                'type': 'hidden',
                'name': 'parent',
                'id': 'comment-parent'
            });
            form.appendChild(input);
        }
        input.setAttribute('value', coid);
        if (null == this.dom('comment-form-place-holder')) {
            var holder = this.create('div', {
                'id': 'comment-form-place-holder'
            });
            response.parentNode.insertBefore(holder, response);
        }
        comment.appendChild(response);
        this.dom('cancel-comment-reply-link').style.display = '';
        if (null != textarea && 'text' == textarea.name) {
            textarea.focus();
        }
        return false;
    },
    cancelReply: function () {
        var response = this.query('.comment-respond')
        holder = this.dom('comment-form-place-holder'), input = this.dom('comment-parent');
        if (null != input) {
            input.parentNode.removeChild(input);
        }
        if (null == holder) {
            return true;
        }
        this.dom('cancel-comment-reply-link').style.display = 'none';
        holder.parentNode.insertBefore(response, holder);
        return false;
    }
};至此!享受你的pjax无刷新技术吧!
 
                         
                         
                         
                         
                     
                     
                     
                     Ryan
            Ryan         
                     
                        
                     
                        
                     
                        
                     
                        
                     
                        
                    
真不错