“仅运行一次 JS”——在 SPA 页面上无副作用的脚本
在单页应用(SPA)页面上,JustZix 会在每次地址变化后重新运行规则集的 JavaScript——以便规则处理刚刚渲染出来的视图。对大多数脚本来说这是好事。但对于带有全局副作用的脚本,这会导致不断累积。新的“仅运行一次 JS”选项解决了这个问题。
问题:脚本被一遍遍运行
SPA 在不重新加载文档的情况下改变内容。JustZix 会检测到这类导航并再次运行规则集的 JS,让规则在新视图上生效。但如果脚本添加了事件监听器、设置了定时器(setInterval),或者“包装”了某个页面函数(例如 window.fetch 或 dataLayer.push),那么每一次重新运行都会再添加一个副本。几次切换之后,你就有了五个相同的监听器、五个并行的定时器,以及一个被包装了五层的函数。
解决办法:“仅运行一次 JS”复选框
规则集编辑器的 JavaScript 选项卡现在多了一个“仅运行一次 JS”的字段(默认关闭——对现有规则集没有任何改变)。勾选后——规则集的 JS 在文档的整个生命周期内只运行一次。SPA 导航、#hash 变化和后退按钮都不会再次运行它。整页重新加载则始终是一次全新的开始。
什么时候勾选它
对以下这些脚本开启“仅运行一次 JS”:
- 添加全局监听器(在
document或window上addEventListener)的脚本, - 设置定时器或超时的脚本,
- 修改
window对象或包装内置函数的脚本, - 设置了某个本身就会自行捕捉后续视图的观察器(
MutationObserver)的脚本。
什么时候保持关闭
对于那些本就该对每一个 SPA 子视图作出反应的脚本,请保持该选项关闭——例如每次都去查找刚刚渲染出来的元素并对它们做些处理的脚本。如果你的脚本是幂等的(多次运行也安全),那你同样不需要改动任何东西。
良好实践:编写幂等代码
不论这个选项如何,编写能够经受重复运行的脚本都是值得的。一个简单的写法是用一个守卫,在脚本已经运行过一次时就中止它:
// 守卫:每个文档只执行一次逻辑
if (!window.__jzMyScript) {
window.__jzMyScript = true;
document.addEventListener('keydown', onKey);
}
“仅运行一次 JS”选项和代码中的守卫是同一种保护的两道防线——你可以同时使用它们。
安装 JustZix,编写能在 SPA 上运行而不会让副作用层层累积的脚本。
为这篇文章评分
暂无评分 — 成为第一个。