当前位置: 首页 > news >正文

【Script执行顺序问题】记一次博客园SimpleMemory主题头像、背景图片、网站的图标失效查错

JavaScript 执行顺序与作用域/依赖关系问题

1.定位问题::昨天发现自己的博客头像、背景图片,网站的图标都失效了,初步推断是后台html自定义代码问题
2.备份数据::把博客侧边栏公告,定制css,页首html,页尾html都做了备份,然后重头开始一点点配置,先引入JS文件:


<script src="https://cdn.jsdelivr.net/gh/BNDong/Cnblogs-Theme-SimpleMemory@v2.1.7/dist/simpleMemory.js" defer></script>

 

然后再一点点把元素都加回上去
3.最后发现是我的代码中一言和博客园配置写在一个script中产生了问题

4.使用通义千问AI辅助理解,它对我的问题解答如下:

你提到“为什么这里分成两块 <script> 就没问题,写成一块就有问题”,这是一个非常典型的 JavaScript 执行顺序与作用域/依赖关系 问题。我们来具体分析。


📌 你的代码结构(简化后):

<script>window.cnblogsConfig = { ... };
</script>

<script>
fetch('https://v1.hitokoto.cn')
.then(...)
.catch(console.error);
</script>

这两段脚本分别做了两件事:

  1. 第一段:定义全局配置对象 window.cnblogsConfig,供博客园主题模板使用。
  2. 第二段:通过 fetch 获取一言 API 数据,并操作 DOM 元素(如 #hitokoto)。

✅ 为什么分开写就没问题?

因为博客园的页面模板是 先加载你的配置(cnblogsConfig再执行页面渲染逻辑最后才执行你写的其他脚本(比如获取一言数据并插入 DOM)。

也就是说:

  • 第一个 <script> 设置了配置 → 博客园系统读取它 → 渲染侧边栏、页脚等。
  • 第二个 <script> 在 DOM 已经生成后运行 → 能正确找到 #hitokoto 元素 → 成功更新内容。

这是 符合执行时序 的。


❌ 如果合并成一块,为什么会出问题?

假设你这样写:

<script>window.cnblogsConfig = { ... };

fetch('https://v1.hitokoto.cn')
.then(response => response.json())
.then(data => {
const hitokoto = document.querySelector('#hitokoto');
// ...
});
</script>

问题在于:这段脚本很可能在 DOM 完全构建之前就执行了!

特别是 #hitokoto 这个元素,是由博客园根据 cnblogsConfig 动态生成的,而这个生成过程发生在你的 <script> 执行之后

所以:

  • 你设置 cnblogsConfig ✔️
  • 紧接着立刻去查 #hitokoto ❌(此时 DOM 还没生成,返回 null
  • 导致后续操作失败(比如 .href 报错)

💡 换句话说:fetch 那部分代码跑得太早了,DOM 还没准备好。


✅ 正确做法(即使合并,也要等 DOM ready)

如果你非要写在一个 <script> 里,必须确保操作 DOM 的代码 在页面渲染完成后执行。可以用以下方式:

方法 1:监听 DOMContentLoaded

window.cnblogsConfig = { /* ... */ };

document.addEventListener('DOMContentLoaded', () => {
fetch('https://v1.hitokoto.cn')
.then(response => response.json())
.then(data => {
const hitokoto = document.querySelector('#hitokoto');
if (hitokoto) {
hitokoto.innerHTML = &lt;a href="https://hitokoto.cn/?uuid=${data.uuid}"&gt;${data.hitokoto}&lt;/a&gt;;
}
})
.catch(console.error);
});

方法 2:用 setTimeout 延迟(不推荐,但有时有效)

window.cnblogsConfig = { /* ... */ };

setTimeout(() => {
// 假设 500ms 后 DOM 已生成
fetch(...).then(...)
}, 500);

但最可靠的是 方法 1保持两个 <script> 分开 —— 因为博客园的渲染机制决定了配置脚本和后续操作脚本天然需要分离。


🔍 补充:博客园的执行流程(推测)

  1. 加载用户自定义 <script>(包括 cnblogsConfig
  2. 博客园 JS 引擎读取 window.cnblogsConfig
  3. 动态生成 HTML 结构(包括 #hitokoto 元素)
  4. 页面继续加载,执行后续 <script>(如你的 fetch)

所以 分开写天然符合这个流程,合并则打破时序。


✅ 总结

情况是否可行原因
分成两个 <script> ✅ 可行 配置先生效,DOM 生成后再操作
合并成一个 <script> ❌ 可能失败 fetch 立即执行,但目标 DOM 尚未创建
合并 + DOMContentLoaded ✅ 可行 等 DOM 准备好再操作

所以,不是“不能合并”,而是“合并后必须等待 DOM 就绪”

建议:保持分开写,清晰、安全、符合博客园的设计预期。




http://www.jsqmd.com/news/55362/

相关文章:

  • 2025 年金华摄影培训人像摄影培训哪家好——路人贾摄影讲堂(金华分公司)排名第一
  • 敏捷冲刺随笔-3
  • 敏捷冲刺随笔-3
  • Elastic Stack 9.1.4版本发布与技术更新
  • 2025 年湖州摄影培训人像摄影培训哪家好——路人贾摄影讲堂(湖州分公司)排名第一
  • 2025 年宁波摄影培训人像摄影培训哪家好——路人贾摄影讲堂(宁波分公司)排名第一
  • 2025年12月deepseek推广服务商推荐,这些deepseek推广公司比较不错
  • 2025 年绍兴摄影培训人像摄影培训推荐榜:路人贾摄影讲堂(绍兴分公司)人像十杰导师亲授、实战化教学典范
  • 2025年12月deepseek推广公司盘点,国内deepseek推广公司推荐
  • MarkDown 常用符号
  • NOIP last dance?
  • 实用指南:数据结构——三十六、拓扑排序(王道408)
  • 单调栈的“贪心”艺术:精雕细琢,打造「最小可能」的数字 - 实践
  • 2025 年桐庐县摄影培训人像摄影培训推荐榜:路人贾摄影讲堂排名第一,从 0 基础到职业摄影师的进阶之路
  • 2025 年淳安县摄影培训人像摄影培训推荐榜:路人贾摄影讲堂(淳安县分公司)技艺领跑、业界金牌导师坐镇
  • 2025 年建德市摄影培训人像摄影推荐榜:路人贾摄影讲堂(建德市分公司)排名第一
  • Rikkahub+硅基流动API-key实现移动端Android-AI女友项目
  • ReactUI 渲染与交互
  • React组件系统
  • 项目.env文件配置以及加载
  • React JSX 语法详解
  • PyTorch 中 model.eval() 的使用与作用详解 - 教程
  • 终曲:NOIP2025游记
  • 豆包能做广告吗?豆包 AI 营销服务商精选推荐 2025年12月
  • 某中心与高校拓展机器人技术学术合作
  • React项目初始化
  • 【图像卷积基础】卷积过程卷积实现通道扩充与压缩池化Pooling原理和可视化 - 详解
  • 15.5.手机设备信息 - 教程
  • 2024csp-s游记
  • 如何选择好的 GEO 服务商?2025年12月优质 GEO 服务商推荐