关于博客中不蒜子与live2D冲突的解决及其根因查找
不蒜子统计数据不展示
很久以前——至少是一年前——我就知道了博客中的「不蒜子」统计功能有些问题,具体原因不记得了,仅仅是记得在哪里看到过,说是和博客主题中使用的另一个什么功能有关。嗯,现在我知道了,是启用了「live2D」导致的。
网络上有很多解决方案,我也不想再一个个写出来了,如果你想的话,可以直接滑到最下面的参考链接,去看看别人写的具体修复方法。
如果你除了直接解决之外,还想大概了解一下原因的话,那么不妨继续往下看。
在博客的模板源代码中,不蒜子的统计信息所在的DOM,默认是 display: none
隐藏的,等待不蒜子获取到数据之后,分别查找对应的DOM并填充数据之后,会修改样式为 display: inline
进而展示出来。
这就是正常情况下的步骤。
那么不正常的情况呢?看一下不蒜子的这段代码吧。
1 | ready(function() { |
上面的 a(b)
函数调用,其中的参数 b
就是统计数据对象,而函数 a
做的事情就是前面说的填充数据而后展示元素。这一步是没问题的,有问题的是下一段代码 scriptTag.parentElement.removeChild(scriptTag)
。在未启用「live2D」时,这段代码正常运行;而启用了「live2D」后,这段代码出现了错误,所以程序进入了错误捕获的代码块 bszTag.hides()
,这个方法就是隐藏统计数据所在元素的方法。
如此看来,你应该也就明白可以如何来修复它了吧。
解决方案
我查到的修复方式不止一种,但说到底,最终针对的也都是上面提到的错误之处。
有人添加一步判断 scriptTag.parentElement && scriptTag.parentElement.removeChild(scriptTag)
,来确保代码不会出错;
另一部分则是去掉统计数据所在元素的容器元素,以 NexT 主题为例,找到 layout/_partials/footer.njk
文件,在文件中找到 <div class="busuanzi-count">
标签,把这个标签下的直接子元素的 ID busuanzi_container_xxxx
删除,以及 layout/_partials/post/post-meta.njk
文件中 ID 为 busuanzi_container_page_pv
的元素删除该 ID 属性。这一种方案的本质其实就是让 bszTag.hides()
失去效果;从上面的截图可以看到, hides()
方法是通过容器元素的ID来找到DOM并设置隐藏的,找不到对应的容器元素,自然也就无法再将其隐藏了。
那么到这里就结束了……吗?
探究根因
很显然并没有。刚刚讲了为什么不蒜子统计会被隐藏掉,但是深究一下,上面的那段代码为什么会出现错误?为什么在启用 live2D 之前没有问题,启用了 live2D 之后就出错了呢?
如果仅仅只看不蒜子的代码,完全不会想到它有什么问题。
1 | bszCaller = { |
不蒜子创建了一个 <script>
标签,然后添加了请求地址,通过 JSONP 的方式获取到统计数据,在设置完数据后,把添加的这个标签移出DOM。这么看下来,是不是完全没有问题?
既然不蒜子的代码看起来没有问题,而且只有启用「live2D」才出现错误,那么自然也需要查看一下「live2D」的源码了。不过我其实是先找到了可能的原因,而后再从 live2D 的代码中搜索关键词查找出来的,毕竟 live2D 的代码都是压缩后的,我也没有一点点分析的耐心。
我是这么想的,不蒜子出现问题时,错误的源头是 scriptTag.parentElement
为空,也就是说 scriptTag
元素不存在父元素。这一点其实很可疑,甚至一度让我怀疑人生:明明前面刚把它添加到 <head>
元素里面,现在你告诉我说,它没有父元素了?
经过了一段时间的自我怀疑、代码检查、debug之后,我终于发现了问题所在:在代码执行到 scriptTag.parentElement.removeChild(scriptTag)
这一句时,scriptTag
与 <head>
里面那个之前创建的 <script>
标签已经不是同一个 DOM 对象了!
1 | scriptTag = document.createElement("SCRIPT"), |
是不是很不可思议?但是结果就是这样,明明应该是同一个元素的,为什么会不一样呢?是什么原因改变了它?
我能想到的答案就是,<head>
元素的内容被重写了。被谁、如何重写的?答案是 innerHTML
属性。
是的,就是它,innerHTML
,这个属性返回 DOM 元素内的 HTML 标签字符串文本,也可以把一段 HTML 字符串添加到 DOM 元素中解析为它的子元素。
而现在,我知道了它的另一个特性,被 innerHTML
重写过的内容,其子元素会产生一个新的 DOM 对象。
于是,找到了问题可能的答案,我就在 live2d-widget 这个包的代码中搜索了 innerHTML
这个关键词,然后找到了一段代码:
于是疑惑终于解除了,我们也都学习到了新的知识点,innerHTML
属性的修改会产生新的 DOM 对象,并导致原本的 DOM 对象被移除无效化。
参考链接
关于和不蒜子计数冲突的问题
Hexo博客不蒜子和live2d看板娘冲突问题解决方案
解决不蒜子(busuanzi)不显示数字问题记录
修补hexo-next不蒜子不显示问题
Hexo NexT 主题不蒜子相关问题汇总