It has been 1485 days since the last update, the content of the article may be outdated.

场景

使用butterfly主题,success@配置全局吸底式播放器 ,需要开启Pjax服务,预加载站内资源。
但是在使用’hexo-charts’,’hexo-calendar’时,出现对象重复创建导致的报错。

类似这样的插件,初始化时会受pjax影响无法二次渲染,只能刷新才能销毁原有的声明对象。
报错信息:
VM5117:1 Uncaught SyntaxError: Identifier ‘calendarChart’ has already been declared
就是说下面这里重复初始化除了问题:
calendar 插件的部分源码

javascript
  <script type="text/javascript">
.......
let calendarChart = echarts.init(document.getElementById('calendar'));
let endDate = new Date().getTime()
.......

求助

网上的建议一大堆,有要求修改pjax源码的,有要修改pjax初始化绑定对象的。
由于次的问题情形都不是很好的解决办法,也无法手动配置Pjax设置,修改源码更不可能,版本差异导致的修改需要自己对pjax源码有充分的理解。
无奈之下求助@HCLonely

获得的建议如下:

  • 使用var 关键字代替let 进行对象的重新创建;
  • 使用自执行函数(function(){ /* code */ })() 进行刷新加载。

都是对插件源码进行修改。看样子没办法了,还好这几个插件的js源码都比较简单。

不想修改源码是因为如果动了博客配置之外的插件或者主题文件的源码,那么你就多一样需要维护的版本了。对于以后的升级,站点项目移植来说还是挺麻烦的。所以尽量使用配置文件和脚本注入,不要动主题源码。

解决

第一个建议很好理解,但是用起来太麻烦,需要修改的变量声明很多
hexo-calendar的源码注入部分:

html
<script>
...
let calendarChart = echarts.init(document.getElementById('${id}'));
let endDate = new Date().getTime()
let startDate = new Date(endDate - ${weeks}*7*24*3600*1000).getTime()
let startDay = Math.ceil(startDate/(24*3600*1000))
let endDay = Math.ceil(endDate/(24*3600*1000))

let commitData = ${commitData}
let seriesData = []
...
</script>

第二条,可以避免上述的问题。对上述的代码进行封装,每次进入页面时会自动销毁重新加载相关对象。
不过这些charts类插件都依赖于Echarts库,所以需要在主题配置文件中注入echarts源。

yml
theme/butterfly/_config.yml
inject:
bottom:
- <script src="https://cdn.jsdelivr.net/npm/echarts@4.8.0/dist/echarts.min.js"></script>

最后修复成功:

最后感谢@HCLonely提供的方案,和包括他在内的开源贡献者提供的众多有趣而实用的插件。