规则里的 MutationObserver —— 一条跟得上页面的规则
你的规则在页面加载后执行 —— 但现代页面并不在加载时就结束了。一个列表拉进更多条目,一个 SPA 换掉整个视图,内容在几秒后才出现。一个 MutationObserver 让规则对启动后发生的事作出反应。
问题:代码只执行一次
一条 JustZix 规则的 JavaScript 执行一次,在页面加载时。如果你隐藏 .promo,而页面在滚动时又加了更多 .promo,你的代码从没见过它们 —— 它们当时还不存在。你需要某个对 DOM 变化作出反应的东西。
三行的 MutationObserver
function apply() {
document.querySelectorAll('.promo').forEach(el => el.remove());
}
apply();
new MutationObserver(apply)
.observe(document.body, { childList: true, subtree: true });
模式总是一样的:一个 apply 函数干活,你立刻调用它一次,然后把它交给 MutationObserver 让它在每次变化时调用。
observe 选项是什么意思
childList: true—— 在子元素被添加或移除时作出反应。subtree: true—— 不只观察直接子元素,而是观察整个子树。没有它,DOM 深处的变化会被漏掉。attributes: true—— 可选:也对属性变化(类名、style)作出反应。
坑一 —— 反馈循环
如果 apply 自己改变 DOM(通常它会),那个变化触发 observer,observer 又调用 apply。对隐藏来说这通常无害 —— 第二遍没什么可做了。但如果 apply 添加东西,给做过的元素打标记:
function apply() {
document.querySelectorAll('.card:not([data-jz])').forEach(el => {
el.dataset.jz = '1';
el.prepend(makeBadge());
});
}
:not([data-jz]) 选择器让你对每个元素恰好处理一次 —— 循环不会失控。
坑二 —— 成本
在非常动态的页面上 observer 触发几百次。让 apply 保持便宜:一个快速的 querySelector、一个「做过」标记、没有沉重的计算。如果它必须很重 —— 用防抖包它(把执行推迟 100 毫秒,每次新变化都重置计时器)。
另见
- 对 DOM 变化有韧性的规则 —— 更宽泛的一套技巧
- 自动展开 —— 实践中的 MutationObserver
- 示例 —— 可供研究的现成规则
安装 JustZix —— 写出跟得上页面的规则。
为这篇文章评分
暂无评分 — 成为第一个。