Typecho博客使用MoOx/Pjax实现pjax
这应该是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无刷新技术吧!