Typecho 主题 PJAX 无刷新以及遇到的一些问题
侧边栏壁纸
  • 累计撰写 13 篇文章
  • 累计收到 2 条评论

Typecho 主题 PJAX 无刷新以及遇到的一些问题

moxne
2023-05-13 / 0 评论 / 13 阅读 / 正在检测是否收录...

最近给 Typecho 主题 Daydream 加上了 PJAX 无刷新。本以为加一段代码就好,结果遇到了一大堆问题,无法提交评论、插件无效、数学公式没法渲染……特此记录一下。

什么是 PJAX
pjax = pushState + ajax
对于传统的 Typecho 主题,实际上就是服务端渲染(SSR)的代表,用户每请求一个页面,服务器(php)就渲染好这个页面的内容(包括文章、评论之类的动态内容),渲染好一个静态的 HTML 然后传给浏览器。这样虽然方便,但是不难发现传输数据量其实不小。在加载不同的页面的时候,有不少部分是重复渲染的,比如页面的页眉、页脚,每个页面都是一样的,但是加载每个页面都要重新加载一次。这就会降低访问体验。

而以调用 Restful 接口等方式进行客户端渲染(CSR)的单页应用程序(SPA)则是与之对立的另一个典型。用户第一次访问只加载一个页面框架,其中的 js 代码通过接口向服务器请求数据,然后在客户端进行渲染。进入新的页面链接时只刷新需要更新的部分(一般是通过 DOM 操作)。这样每次只需要修改页面中很少的信息量,可以加快加载的速度。这称为无刷新技术。然而 Typecho 并不是以这种 CSR 的思路构建的。
(我之前开过的一个坑 Vuecho 其实就是这种尝试,这是一个 demo:alpha.skywt.cn)

那么 PJAX 实际上就是以上两者的「折中方案」。通过这段神奇的 js 代码,它可以自己判断哪些部分刷新了,然后在刷新(或者进入新的页面)时通过 DOM 操作更新要更新的部分。虽然后端的实现完全是服务器端渲染,但是前端看起来就好像是客户端渲染一样,实现全站无刷新,可以获得非常迅捷的体验。

给 Typecho 主题加上 PJAX
⚠️ 本文使用的是 jquery-pjax。

这一步其实非常简单(麻烦的在后面),
首先把博客的动态内容(即从一个页面进入另一个页面要更新的内容)用一个

之类的标签包裹起来,并将 id 设置为 pjax-container。这个容器就叫做 PJAX 容器。
在这个容器外部,是刷新页面不需要更新的部分,如每个页面都一样的页眉、导航栏、页脚。
在这个容器内部,是刷新页面需要重新加载的部分,比如从文章列表进入一篇文章,容器中的内容由「文章列表」改变为「文章内容」。

一般主题的结构包含 header.php、footer.php,只要在 header.php 的末尾加上容器的开放 tag,在 footer.php 的开头加上容器的封闭 tag 即可。最后渲染出来的页面应该像是这样:

<head>
    <!-- ... -->
</head>
<body>
    <header><!-- 页眉,标题什么的 --></header>
    <nav><!-- 导航栏什么的 --></nav>
    <main id="pjax-container">
        <!-- 网站主体内容,文章列表 / 文章内容 / 评论什么的 -->
    </main>
    <script>
        // 下面要加上的代码
    </script>
    <footer><!-- 页脚什么的 --></footer>
</body>


在 footer.php 或者其他地方(PJAX 容器的后面,就是上面这段代码的