Typecho 主题开启 Pjax 后评论出现的问题解决方案

4 年前(已编辑)
1485
1
这篇文章上次修改于 3 年前,可能部分内容已经不适用,如有疑问可询问作者。

问题复现

在开启 Pjax 后,一般会重载一个主容器,而不会重载 Head 标签,问题是 Typecho 的评论脚本在 Head 里,如下图。

注意,红色框标注,可以看出这段脚本是根据当前页的 cid 来判断评论框所在位置。

这里补充一下,在回复评论的时候 Typecho 的评论框是会移动的,根据的就是圈注的红框,他会去找 DOM 中有没有这个元素,如果没有找到,那么就报错了,页面就会刷新,失去了整站无刷的体验。

思考过程

首先想到重载 head 标签,发现这是不可行的,因为在替换元素的一瞬间,CSS 样式被移除,网站会突然变成纯 HTML 的样子。

那么就只能从 script 标签入手了,获取到 head 第一个 script 标签,这里刚刚是第一个,选择器为 script[type],进行替换里面的内容。

尝试用正则替换,不可信,因为改完之后没有重新执行这段代码。

解决方案,使用 eval() 函数立即执行,首先要获取到原代码的内容,拷贝一份进行修改,修改的 cid 可以使用 PHP 获取当前页面的 cid。

完整代码如下,放在 post.php 末尾即可 ```js (function () { const commentFunction = document.querySelector('head').querySelector('script[type]') const innerHTML = commentFunction.innerHTML if (innerHTML.match(/this.dom('respond-.*?')/ig)) { const after = innerHTML.replace(/this.dom('respond-.*?')/ig, "this.dom('respond-post-<?php $this->cid() ?>')") eval(after) }

js else { const script = document.createElement('script') script.innerHTML = ` (function () { window.TypechoComment = { dom : function (id) { return document.getElementById(id); },

})(); ` document.head.insertBefore(script, commentFunction) eval(script.innerHTML) } ```

后续

后来在 Chrome 中遇到了 Maximum call stack size exceeded 的问题,简单地说就是堆栈溢出了。因为平时使用 Cent Browser 开发所以没怎么注意到这个问题。那就只能再改呗。那只能改的更傻瓜一点了。

今天遇到的问题 浏览器在执行 IIFE 函数时,浏览器会在头部 head 标签加入一个 <script type="text/javascript" id> 的标签,所在 IIFE 内部使用 script[type] 可能会捕获到自身,并非自己理想状态的 null

补充说明

eval() 导致的堆栈溢出可以采用 setTimeOut() 解决。

完整代码:https://github.com/Innei/Typecho-Theme-Paul/blob/master/comments.php

评论区加载中...