hexo-theme-icarus 主题适配 Pjax

hexo-theme-icarus 主题适配 Pjax

我发现 Pjax 能极大增加页面切换的流畅度。于是我着手适配。

参考文章:

初步实现

原理

Pjax 拦截用户的跳转请求,用 Ajax 使页面局部更新使页面无需完全重载。

选择

前者依赖 jQuery。我选择后者。

分析

hexo-theme-icarus 主题在更改页面时,会更改的内容有:

  • title 标题
  • head 元素内的一些 meta 信息什么的
  • .navbar-start.navbar-start 顶栏的几个选项的高亮
  • .columns 文章和插件
  • #back-to-top 返回页顶的按钮

设置并初始化 Pjax

source/js/SetPjax.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 初始化并设置哪些需要改变
var pjax = new Pjax({
selectors: [
"head title",
".columns",
".navbar-start",
".navbar-end",
".searchbox",
"#back-to-top",
".pjax-reload"
],
});

// 包含一些 Pjax 加载后需要重新执行的函数
function pjax_reload() {
// 需要重新执行的函数写在这
}

// 监听 Pjax 完成后,重新加载上面的函数
document.addEventListener("pjax:complete", function () {
pjax_reload();
});

脚本中添加了 .pjax-reload[data-pjax] 。若切换页面时,某些元素需重新加载,可添加 .pjax-reload 到该元素,脚本可添加 [data-pjax] 属性。

利用 Hexo 注入器功能引入 Pjax 和初始化脚本:

scripts/inject.js
1
2
3
4
5
6
7
8
9
const js = hexo.extend.helper.get('js').bind(hexo);

hexo.extend.injector.register('head_end', () => {
return js('//lib.baomitu.com/pjax/0.2.8/pjax.min.js');
});

hexo.extend.injector.register('head_end', () => {
return js('/js/SetPjax.js');
});

一些问题

现在 Pjax 的适配已经基本完成,切换页面明显顺畅了许多。 但仍有一些 hexo-theme-icarus 主题相关的问题:

  • #back-to-top 返回页顶按钮在 Pjax 后消失;
  • Pjax 后 footer 消失,疑似与上一条相关;
  • 语法高亮不可用;
  • 代码框样式不同,无法折叠,无复制按钮;
  • 图片不显示描述,无法点击查看大图;
  • 移动端导航栏目录遮罩失效(缺少 div#toc-mask );

只要找到相关函数并添加到需要重新执行的函数内即可解决问题。奈何我能力有限,我暂且先去 Github 询问主题作者相关信息。

改进

提交更改至主题。

配置文件相关

include/schema/plugin/pjax.json
1
2
3
4
5
6
7
+ {
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "$id": "/plugin/pjax.json",
+ "description": "Enable PJAX",
+ "type": "boolean",
+ "default": true
+ }

欲加载的标签打上标记

layout/common/scripts.jsx
1
2
3
4
5
6
7
8
9
@@ -35,9 +35,9 @@ module.exports = class extends Component {
{clipboard && <script src={cdn('clipboard', '2.0.4', 'dist/clipboard.min.js')} defer></script>}
<script dangerouslySetInnerHTML={{ __html: `moment.locale("${language}");` }}></script>
<script dangerouslySetInnerHTML={{ __html: embeddedConfig }}></script>
- <script src={url_for('/js/column.js')}></script>
+ <script data-pjax src={url_for('/js/column.js')}></script>
<Plugins site={site} config={config} page={page} helper={helper} head={false} />
- <script src={url_for('/js/main.js')} defer></script>
+ <script data-pjax src={url_for('/js/main.js')} defer></script>
layout/plugin/back_to_top.jsx
1
2
3
4
5
6
7
8
9
@@ -9,7 +9,7 @@ class BackToTop extends Component {
<a id="back-to-top" title={title} href="javascript:;">
<i class="fas fa-chevron-up"></i>
</a>
- <script src={jsUrl} defer></script>
+ <script data-pjax src={jsUrl} defer></script>
</Fragment>;

}

新增 PJAX 插件

layout/plugin/pjax.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@@ -0,0 +1,18 @@
+ const { Component, Fragment } = require('inferno');
+
+ class Pjax extends Component {
+ render() {
+ if (this.props.head) {
+ return null;
+ }
+ const { helper } = this.props;
+ const { url_for, cdn } = helper;
+
+ return <Fragment>
+ <script src={cdn('pjax', '0.2.8', 'pjax.min.js')}></script>
+ <script src={url_for('/js/pjax.js')}></script>
+ </Fragment>;
+ }
+ }
+
+ module.exports = Pjax;

初始化脚本

source/js/pjax.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@@ -0,0 +1,36 @@
+ // eslint-disable-next-line no-unused-vars
+ let pjax;
+
+ function initPjax() {
+ try {
+ // eslint-disable-next-line no-undef
+ pjax = new Pjax({
+ selectors: [
+ 'head title',
+ '.columns',
+ '.navbar-start',
+ '.navbar-end',
+ '.searchbox',
+ '#back-to-top',
+ '[data-pjax]',
+ '.pjax-reload'
+ ]
+ });
+ } catch (e) {
+ console.warn('PJAX error: ' + e);
+ }
+ }
+
+ // // Listen for start of Pjax
+ // document.addEventListener('pjax:send', function() {
+ // return;
+ // // TODO pace start loading animation
+ // })
+
+ // // Listen for completion of Pjax
+ // document.addEventListener('pjax:complete', function() {
+ // return;
+ // // TODO pace stop loading animation
+ // })
+
+ window.addEventListener('DOMContentLoaded', () => initPjax());
作者

PJ568

发布于

2024-02-25

更新于

2024-04-29

许可协议

评论