前言

我们都知道,butterfly主题是支持pjxa,但是号称bug御三家之一的pjxa岂是我这样的小白能轻易玩明白的,那么我究竟遇到了什么问题呢?最大的问题是开启了pjxa后有些js会失效,不明白什么原因。就在前几天,我决心会一会pjxa,于是百度了一下,也参考了几篇相关文章,总算大概有了些眉目,对其运行机理也有了初步认识,且解决了一些问题。所以,无论何事,不能盲目去干。所谓工欲善其事,必先利其器,古人诚不欺我!

为何要使用pjxa?

Pjax能够实现页面的局部刷新而非整体重载资源,在一定程度上能够减少网站反复加载重复资源,从而优化访问体验。

参考文章

进入正题

data-pjax属性的使用

在魔改主题时,肯定会不可避免的添加一系列第三方js,此时就会遇到切换页面后,由于通过 Pjax 切换的页面并没有完全刷新,浏览器不会将网页从头执行一遍,因此有些JS将不会生效。这也是我经常遇到的问题。

在script标签中添加了data-pjax属性的的js,在页面切换后执行重载,达到局部刷新的效果。所以我们要做的事情十分简单,给这些js引入的位置添加data-pjax属性即可。比如:

1
2
3
4
5
6
7
8
inject:
head:
# 首页电子钟
- <link rel="stylesheet" href="/clock/css/clock.css"/>
bottom:
# 首页电子钟
- - <script src="/clock/js/clock.js"></script>
+ - <script data-pjax src="/clock/js/clock.js"></script>

使用data-pjax的过程中,务必考虑到变量被反复声明的问题。例如在clock.js中,有用const定义了api密钥的常量,但是添加data-pjax之后,切换页面时会反复声明这个常量。和const的生命周期起冲突。解决方案有(以下方案二选一即可,全部都做反而有bug)

  • 把声明常量的代码放到单独的js中,并且不加data-pjax。

  • 将const声明改成用let或者var声明。

.js-pjax的使用

只要是在类名为js-pjax元素包裹下的内容就会执行局部重载。比如:

1
2
3
4
.js-pjax
script.
bot_ui_ini()
// 可以是函数引用,可以是代码片段。甚至可以是任何需要重载的网页元素。

处理事件绑定问题

有时候,js里面会这么写:

1
2
3
4
5
6
7
8
9
10
11
$(document).ready(()=>{
//todo
})
//或者
window.onload=function(){
//todo
}
//或者
window.addEventListener("DOMContentLoaded",()=>{
//todo
})

这些写法在pjax下的表现就是首次加载执行,后面就不会执行了。

修改方法也不难,把所有要做的事情全部写在一个函数里面,绑定事件:

1
2
3
4
5
window.addEventListener("pjax:complete",todo);//后面几次,pjax加载
window.addEventListener("DOMContentLoaded",todo);//第一次
function todo(){
//代码
}