跳转至

🛌 NexT主题启用PJAX

壹丨什么是 PJAX?

PJAX,即 PushState + Ajax,封装成一个 jQuery 扩展以方便使用。PJAX 主要用来解决 HTML 页面局部刷新 url 不更新和不支持后退和前进的问题,提升用户体验。

通俗来讲:

没有 PJAX 时:点击页面上的按钮,网页将清除当前显示页,载入指向页的全部内容,加之网络延迟等原因,会出现短暂的整幅网页为空白页。

开启 PJAX 时:点击页面上的按钮,指向页和当前页相同的元素,如导航栏、音乐播放器等不需要重新加载,而不同的局部页面内容将刷新并加载。

贰丨NexT主题使用 PJAX

Hexo 的 NexT 主题已经集成 PJAX:

修改~/hexo-site/_config.next.yml

- pjax: 
+ pjax: true

仅仅在主题文件中启用 PJAX 局部刷新后,一些插件会失效,本博客失效的插件有:gallery视图插件hexo-next-photos、豆瓣电影插件hexo-douban、音乐插件aplayermeting

叁丨解决插件失效问题

原理:在添加插件的位置重新加载CSS、JS文件。

1. APlayer、Meting 音乐插件——切换界面音乐不停

这类可以通过修改 HTML 代码导入 CSS、JS 文件:

【侧边栏添加全局音乐播放插件】

第一步,修改 ~/hexo-site/_config.next.yml

- #sidebar: source/_data/sidebar.njk
+ sidebar: source/_data/sidebar.njk

第二步,~/hexo-site/source/_data/ 中,增加文件 sidebar.njk ,编辑如下:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title></title> 
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css">
        <script src="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/Meting.min.js"></script>
    </head>
    <body>
        <meting-js server="netease" type="playlist" id="6922083348" autoplay="true" order="random" list-folded="true"></meting-js>    
    </body>
</html>

2. 画廊插件 hexo-next-photos

使用图床模式,插件将 ~/hexo-site/node_modules/hexo-next-photos/lib/figureBed.js 生成 photo.js ,丢到 ~/hexo-site/public/js/

插件失效解决原理:检测到 ImageGrid 的类,就重新加载一次CSS、JS。

修改 ~/hexo-site/themes/next/source/js/pjax.js,添加:

const pjax = new Pjax({....)}
...
//添加以下代码
var dynamicLoading = {
    css: function(path){
        if(!path || path.length === 0){
            throw new Error('argument "path" is required !');
        }
        var head = document.getElementsByTagName('head')[0];
        var link = document.createElement('link');
        link.href = path;
        link.rel = 'stylesheet';
        link.type = 'text/css';
        head.appendChild(link);
    },
    js: function(path){
        if(!path || path.length === 0){
            throw new Error('argument "path" is required !');
        }
        var head = document.getElementsByTagName('head')[0];
        var script = document.createElement('script');
        script.src = path;
        script.type = 'text/javascript';
        head.appendChild(script);
    }
}

然后再添加:

document.addEventListener('pjax:success', () => {
...
NexT.utils.updateSidebarPosition();

// 添加以下代码
if(document.getElementsByTagName("ImageGrid")){
    //动态加载 CSS 文件
    dynamicLoading.css("/css/gallery.css");
    //动态加载 JS 文件
    dynamicLoading.js("/js/photo.js");
}

3. 豆瓣电影插件 hexo-douban

根据以上思路,只要在 pjax.js 中添加进要加载的 CSS、JS 即可,当然最重要的是找到要追踪的类名。

第一步,定位插件显示位置,位于 <div class="post-body animated fadeInDown"> 下:

第二步,逐行分析:

<blockquote> ... </blockquote> <!--这是一开始的那个quote块-->
<style> ... </style> <!--这是样式(CSS)文件>
<div class="hexo-douban-tabs"> ... </div> <!--这是显示豆瓣电影 在看/想看/已看 的div标签-->
<div> ... </div> <!--这里放的是 首页/上一页/页码/下一页/尾页 的标签-->
<script> ... </script> <!--这里是JS文件-->

所以,把 <style> ... </style> 内容保存为 douban.styl ,放在 ~/hexo-site/themes/next/source/css/ 下;把 <script> ... </script> 保存为 douban.js ,放在 ~/hexo-site/themes/next/source/js/ 下;

因为,在执行 hexo g 的时候,~/hexo-site/themes/next/source/css/~/hexo-site/themes/next/source/js/ 两个文件夹中的文件会拷贝到 ~/hexo-site/public/css~/hexo-site/public/js 文件夹下。

第三步,继续分析:

包含 envent<a> </a> 标签在分别存放在两个类下:

<div class="hexo-douban-tabs"> ... </div>
<div class="hexo-douban-pagination"> ... </div>

所以,在 ~/hexo-site/themes/next/source/js/pjax.js 中添加:

if(document.getElementsByTagName("hexo-douban-tabs")){
    //动态加载 CSS 文件
    dynamicLoading.css("/css/douban.css");
    dynamicLoading.js("/js/douban.js");
}
if(document.getElementsByTagName("hexo-douban-pagination")){
    //动态加载 CSS 文件
    dynamicLoading.css("/css/douban.css");
    dynamicLoading.js("/js/douban.js");
}

因为没学过前端的 HTML、JS、CSS 这些,如有错误,希望不吝赐教

参考

[1] FHB科学院,樊浩柏,PJAX原理和使用

[2] 米米的博客,张书樵,NexT 适配 PJAX 的方案

[3] 程序员甜品店,Jefsky,解决pjax加载页面导致js插件失效

[4] 木皆之森,Raoby,pjax无刷新加载后百度统计失效解决方案

[5] 小乐的博客,XiaoLe,解决next主题开启pjax时使用hexo-blog-encrypt无效