前言

之前自己的网页pjax时灵时不灵,真的是奇了怪了。研究了一下pjax的文档,发现很多东西都是用的有问题,因为最开始魔改页面的时候都没注意过pjax,所以留下了大量垃圾代码。

这个文章可以更好的帮助你去魔改页面,并且保留pjax。

页面跳转

pjax的element是用来告诉pjax,点击这个东西就要触发pjax啦!使用butterfly的小伙伴可以发现,pjax.pug文件中是对所有a标签进行了注册。但是有的时候我们是使用onclick进行页面跳转的,而这个元素并不是a标签。

1
#bber-talk.swiper-wrapper(onclick=`window.open('/essay/','_self')`)

这种方式打开的链接不符合注册条件,所以点击之后不可能是pjax的跳转。

我们可以使用pjax文档的pjax.loadUrl("/your-url")来进行跳转

1
#bber-talk.swiper-wrapper(onclick=`pjax.loadUrl("/essay")`)

文档信息:

loadUrl(href, [options])

使用此方法,你可以手动触发 URL 的加载:

1
2
3
4
5
6
7
var pjax = new Pjax()

// use case 1
pjax.loadUrl("/your-url")

// use case 2 (with options override)
pjax.loadUrl("/your-other-url", { timeout: 10 })

所以当你自己魔改的时候添加了非a标签的跳转,可以检查是否被加入到element中,如果没有的话一个是可以通过将dom元素通过css选择器的方式添加到element中,也可以通过我上面提到的loadurl来做。既然是魔改,原文件肯定动的越少越好维护,所以推荐使用loadurl,在自己的代码上做改动。

js-pjax滥用

文档对于selectors有明确的提示:

注意: 如果当前页面和新页面没有相同数量的 DOM 元素,Pjax 将回退到正常页面加载。

这要求了跳转前后更新的dom元素数量相同。而如果你自己创建的js-pjax在之前/之后页面只拥有一个,那么这个页面将会不使用pjax进行跳转。

正确例子:

在footer中插入了一个.js-pjax元素,因为所有页面都有footer,所以元素数量保持不变,可以刷新,正常执行。

错误例子:

在一个只有首页有的元素中插入了一个.js-pjax元素,因为只有首页有,所以只要链接经过首页,那么将不使用pjax运行。

js重载

那么当我们需要使用pjax跳转网页后重新加载js的时候该怎么办呢?

  • 如果是整个js文件加载
    butterfly的话就使用data-pjax属性来让js文件重载,因为这个是butterfly中写好的规则:

    1
    2
    3
    4
    5
    6
    7
    document.querySelectorAll('script[data-pjax]').forEach(item => {
    const newScript = document.createElement('script')
    const content = item.text || item.textContent || item.innerHTML || ""
    Array.from(item.attributes).forEach(attr => newScript.setAttribute(attr.name, attr.value))
    newScript.appendChild(document.createTextNode(content))
    item.parentNode.replaceChild(newScript, item)
    })

    所以我们可以在配置文件或者页面中引入

    1
    <script src="https://cdn.zhheo.com/JS-Heo/bb/showbb_in_index.js" data-pjax="" defer=""></script>

    也可以在footer中插入一个.js-pjax来添加到pjax的selectors作为重载的dom(顺便就会重载js)

    1
    2
    3
    #footer
    .js-pjax
    reloadFunction()

    butterfly用户也可以在themes/butterfly/layout/includes/additional-js.pug这个文件后面插入。

  • 如果是函数重新运行
    那么我们可以使用pjax的监听规则,当pjax加载完毕后,我们就可以执行。例如:

    1
    2
    3
    document.addEventListener('pjax:complete', (e) => {
    onlyHome()
    })

    Butterfly我们可以在themes/butterfly/layout/includes/third-party/pjax.pug中找到pjax:complete在后面添加我们需要执行的函数即可。
    当然我们也可以把函数放在前面那个js文件加载的方式来运行

附加:减少Pace的加载时间

pjax的最佳搭档就是pace了,一个小进度条可以跟踪pjax的加载进度,非常的方便。但是遇见卜算子、百度统计的崩溃大户,我们会经常卡进度,为了避免卡进度,并且这些js运行与网站并没有什么关系,所以我们可以添加pace的属性来排除掉这些加载。

关闭restartOnRequestAftereventLag

1
<script data-pace-options='{ "restartOnRequestAfter":false,"eventLag":false}' src="https://cdn.jsdelivr.net/npm/pace-js@latest/pace.min.js"></script>

参考链接:https://blog.zhheo.com/p/3e567fa7.html