VOID の Pjax 特性

这篇文章并不是从零开始添加 Pjax 特性,只是在 Typecho-Theme-VOID 3.3.0 基础上为主题添加了两点适配。

  • Links 随机输出的 Pjax 支持
  • Hitokoto 的 Pjax 支持

距离上次发布 Links 插件链接随机排序 的文章已经过去 158 天了,当时虽然用半吊子的 JavaScript 水平实现了友链模块随机输出的功能,但是 VOID 主题的 Pjax 特性一直添加不上去,后来我干脆直接放弃 Pjax 裸奔。虽然得益于阿里 CDN OSS 双加持还有 InstantPage.js 、主题的优化等,网站的访问速度一直尚可。

但是最近折腾目前主题作者的 PandaBangumi 插件发现这个追番插件和主题代码风格一致、追番的展示模块也支持了无刷新加载特性(发布博文称方式是 Ajax ),在 PandaBangumi.js 文件末尾我发现了这样的结构:

function initCollection(){
    // function...
}

$(document).ready(function(){
    initCollection();
})

$(document).on('pjax:complete', function () {
    initCollection();
})

这帮助我理解了主题设置中的 Pjax 重载函数项,所有需要重载的函数都活在 $(document).on('pjax:complete', function(){ }) 中。并且查看源代码可以发现重载的内容都带有 pjax-containerid 属性。以此为前提我开始折腾适配。


Hitokoto 适配

最初我使用的 Hitokoto 是旧版本 VOID 主题遗留的代码,更新版本后一言功能被删去我觉得还想要,于是翻旧版本代码又把功能找回来了。

<!-- 主题后台设置中或 included/head.php 中 <head> 前引入 API js -->
<script src="https://v1.hitokoto.cn/?encode=js&select=%23hitokoto"></script>

<!-- 页面需要输出一言的地方写入 id="hitokoto" 的元素-->
<p id="hitokoto"></p>

后来由于引入 v1.hitokoto.cn 的 js 控制台会显示跨域警告,好像是说最新版 Chrome 浏览器(版本号 80 )默认屏蔽所有第三方 Cookie 可能引起跨域资源无法访问,需要增加 Samesite 字段兼容,至于那是什么我还不明白。我在网上找到了 秋のかえで 写的可以放在本地的较简单的一言 API ,调用本地 .txt 文件输出。将上面的 script 地址替换为 https://monsterx.cn/API/Hitokoto/?code=js 即可。 (翻代码的时候,我居然发现我在主题里多处引用重复的 API JavaScript 等。说来惭愧,Alan 大佬的主题在我手上被修改的体无完肤,有的时候我自己都看不下去)

用返回 js 格式的数据的时候我发现 Chrome 又给我报错说不建议使用 document.write 什么的,困惑之余我打开 API 地址发现返回的是:

function getHitokoto(){document.write("“像你这样的白痴是怎么活过来的?”“因为我很自信。");}

这里用了 document.write 方法是不推荐的,所以我尝试换成 json 格式返回数据。啊,又是你,JSON!这里用到了在 PandaBangumi.js 学到的 $.getJSON()

<!-- 删掉之前在 head 前引用的 <script> 标签 -->
<!-- 直接写段 Javascript 处理返回的 json -->
<script type="text/javascript">
function getHitokoto() {
    var url = 'https://monsterx.cn/API/Hitokoto/?code=json';
    $.getJSON(url, function (json) {
        document.getElementById("hitokoto").innerHTML = json.msg;
    });
}

$(document).ready(function () {
    getHitokoto();
})

// 为了适配 Pjax 特性,在 VOID 设置 Pjax 重载函数中加入 getHitokoto(); 
// 或者在 javascript 继续添加下面这段代码
// $(document).on('pjax:complete', function () {
//     getHitokoto();
// })
</script>

<!-- 需要输出一言的地方写入 id="hitokoto" 的元素-->
<p id="hitokoto"></p>
<!-- 为了适配 Pjax 需要添加 id="pjax-container" -->
<div id="pjax-container"><p id="hitokoto"></p></div>

好啦,这样就完成了。


Links 随机输出适配

上次的 文章 中我这样写道:

根据评论区 ZigZagK 同学提醒,VOID 开启 Pjax 后会出现异常。需要把 这段代码 放入重载函数中。

但是当时我尝试了之后并不知道到底该放什么进去,就很尴尬地草率地收尾了。。。最近看 js 看得有点多有了点思路,下面是适配成功的教程。

翻看上次的文章,我写的是用 Typecho 插件接口 php 输出数据到 js 数组中,然后通过随机排序、遍历输出,整段代码没有写在函数中。(虽然当时我也尝试在独立的 function 中写,但当时很显然没有处理好 .sort() 方法的参数和 function 的用法)修改后的 JavaScript 代码如下:

function randomFunc(){
    return ( Math.random() - 0.5 );
}
function getLinks(){
    if ($("#randomLinks").length>0) {
        var arr = [
            <?php if (class_exists("Links_Plugin")): ?>
            <?php Links_Plugin::output('
                {\'url\': \'{url}\',\'name\': \'{name}\',\'slogan\': \'{description}\',\'logo\': \'{image}\'},
            ',0); ?>
            <?php endif; ?>
            {'url': 'https://tingle.dev/','name': 'Tingle','slogan': 'Aurora Blog','logo': 'https://cdn.monsterx.cn/img/logo/MonsterX.jpg'}
        ];
        arr.sort(randomFunc);
        var sHtml = '';
        for(var i = 0; i < arr.length; i++) {
            sHtml += '<div class="board-item link-item"><div class="board-thumb" data-thumb="' + arr[i].logo + '"><img class="lazyload instant loaded" data-src="' + arr[i].logo + '" src="' + arr[i].logo + '"></div><div class="board-title"><a target="_blank" href="' + arr[i].url + '">' + arr[i].name + '</a></div><div class="board-title description"><small>' + arr[i].slogan + '</small></div></div>';
        }
        document.getElementById("randomLinks").innerHTML = sHtml;
        console.log('%c getLinks() %c 后宫以待 ', 'color: #fadfa3; background: #030307; padding:5px 0;','background: #fadfa3; padding:5px 0;');
    }
    else {
        console.log('%c getLinks() %c 无事可做 ', 'color: #fadfa3; background: #030307; padding:5px 0;','background: #fadfa3; padding:5px 0;');
    }
}

$(document).ready(function(){
    getLinks();
})

这里新建了 getLinks() 的函数,比之前版本新增的就是多了一层判断:

if ($("#randomLinks").length>0) {
    // ...
}
else {
    // ...
}

这是用来判断页面中是否存在 id 属性值为 randomLinks 的元素的 js 。在反复尝试无这层判断时适配 Pjax ,发现总会出奇怪的错误,Pjax 载入时不显示输出 console 报错找不到属性值为 randomLinks 的元素。这一切都源于我并不理解 Pjax 是什么,怎么实现的。在读完《让你的网站实现 PJAX 无刷新 - 保罗的小宇宙》,更多的理解 Pjax 的实现之后我开始明白为什么报错该怎么解决。

Pjax 载入友链页面时这段 js 并没有加载出来,虽然刷新出了友链模块的 div 块,但是并没有执行的动作,所以啥也显示不出来。为什么没加载?因为我在输出这段代码之前加了判断,只有在友链页面才会输出这段 js ,Pjax 加载时似乎并没有理会我在 php 的判断,没有输出。那么我就将这层判断删去,让所有页面都加载。(相较于我的那些图片,这点 js 算什么,加载速度影响微乎其微)

然后出现了第二个问题:console 报错,大致意思是找不到属性值为 randomLinks 的元素。为什么呢,你找不到就找不到呗,你不执行就那呆着能咋地?你报啥错?给你闲的!...哦是我给你布置了任务啊?那没事了。因为在每次页面加载的时候我都执行 getLinks() 函数,然后 js 就想方设法完成任务:随机输出友链,可是找了半天没有纸没有笔无奈抛出了错误。那行吧,我一想:害,给你找点事干!先判断 html 页面中是否存在 idrandomLinks 的元素,有就输出,没有就呆着玩控制台吧!所以有了:

function getLinks(){
    if ($("#randomLinks").length>0) {
        // Output Links...
        document.getElementById("randomLinks").innerHTML = sHtml;
        console.log('%c getLinks() %c 后宫以待 ', 'color: #fadfa3; background: #030307; padding:5px 0;','background: #fadfa3; padding:5px 0;');
    }
    else {
        console.log('%c getLinks() %c 无事可做 ', 'color: #fadfa3; background: #030307; padding:5px 0;','background: #fadfa3; padding:5px 0;');
    }
}

最后还有一点,那就是将 getLinks(); 放入 Pjax 重载函数,还有友链输出的地方添加 id="pjax-container"

<div id="pjax-container">
    <div class="board-list link-list" id="randomLinks"></div>
</div>


调试的时候还发现了 PandaBangumi 插件与主题 Pjax 使用的小问题,这里一并记下来

开启 Pjax 功能后我将 initCollection(); 函数也放在了主题设置的 Pjax 重载函数中,并给默认的输出 div 套上了一层 id="pjax-container",像这样:

<!-- 默认输出 -->
<div data-type="watching" class="bgm-collection"></div>

<!-- 我操作后 -->
<div id="pjax-container">
    <div data-type="watching" class="bgm-collection"></div>
</div>

事实证明这是多此一举,这样会导致追番模块重复加载,一个变俩,就连“加载更多”的按钮也一个变俩。

删掉 <div id="pjax-container"> ,只需要在 你发现 PJAX 切换页面时番剧都不加载了 的情况下 去主题的 PJAX 回调函数中添加一句 initCollection ();,否则什么也不需要做。

有的时候认真读说明书真的特别重要。

添加新评论

本站现启用评论投票,被踩的太多就会自动折叠 QwQ ,快来试试吧 ~
评论提交失败请点Artalk备用评论


已有 4 条评论

你总算营业了@(赞一个)

感觉好厉害啊,赞一个~

我本来也想加一言来着,结果发现我找不到合适的地方放
(小声:我的链接去到了其他地方QAQ)

不好意思哈哈哈,链接跑串了