观察目标节点上尚不存在的突变
Posted
技术标签:
【中文标题】观察目标节点上尚不存在的突变【英文标题】:Observe mutations on a target node that doesn't exist yet 【发布时间】:2016-12-17 07:17:23 【问题描述】:是否可以在尚不存在的 DOM 节点上观察突变?
示例:
我的应用有时会创建一个 div:<div id="message" data-message-content="foo" data-message-type="bar" />
。
我想关注这个 div 的创建和变化。
var mutationObserver = new MutationObserver(function(mutations)
// Some code to handle the mutation.
);
mutationObserver.observe(
document.querySelector('#message'),
attributes: true,
subtree: true,
childList: true,
characterData: false
);
);
现在这会返回一个错误,因为#message
为空(尚未创建 div)。
Failed to execute 'observe' on 'MutationObserver': parameter 1 is not of type 'Node'.
一个明显的解决方案是观察body
并检查是否有任何突变是div#Message
的创建,但这似乎是个坏主意/或者可能对性能不利。
【问题讨论】:
你是如何创建元素的?您不能在创建它的相同方法中添加它以便实际创建它吗? 很遗憾,它是针对 Google Chrome 插件的。插件有一些恼人的范围限制。基本上,这个观察者存在于与创建 div 的窗口/函数完全不同的范围内。 显而易见的解决方案是唯一的解决方案,除非站点在添加该节点之前发出某种事件。Refer this answer how I fixed it
***.com/questions/61212681/…
【参考方案1】:
只能观察现有节点。
但不要担心,因为 getElementById 与枚举所有突变的添加节点相比非常快,所以等待元素出现根本不会像您在 Devtools -> Profiler 面板中看到的那样费力。
function waitForAddedNode(params)
new MutationObserver(function(mutations)
var el = document.getElementById(params.id);
if (el)
this.disconnect();
params.done(el);
).observe(params.parent || document,
subtree: !!params.recursive || !params.parent,
childList: true,
);
用法:
waitForAddedNode(
id: 'message',
parent: document.querySelector('.container'),
recursive: false,
done: function(el)
console.log(el);
);
始终使用 devtools 分析器并尝试使您的观察者回调消耗的 CPU 时间少于 1%。
尽可能观察未来节点的直接父节点 (subtree: false
)
在 MutationObserver 回调中使用 getElementById、getElementsByTagName 和 getElementsByClassName,避免使用 querySelector,尤其是速度极慢的 querySelectorAll。
如果在 MutationObserver 回调中绝对无法避免 querySelectorAll,请先执行 querySelector 检查,平均而言这样的组合会快得多。
不要在 MutationObserver 回调中使用需要回调的数组方法,如 forEach、filter 等,因为在 javascript 中,函数调用与经典的 for (var i=0 ....)
循环相比是一项昂贵的操作,并且 MutationObserver 回调可能每秒触发 100 次在复杂的现代页面上,每批突变中有数十、数百或数千个addedNodes
。
请勿在 MutationObserver 回调中使用 the slow ES2015 loops 之类的 for (v of something)
,除非您进行了转编译并且生成的代码运行速度与经典的 for
循环一样快。
【讨论】:
Welp,这是我在这里得到的最深入(关于性能)的答案之一。谢谢! 一种巧妙的方法,因为您不依赖于突变属性(我遇到了困难),而是每次都检查所需的元素是否存在。有点像超时轮询。虽然依赖于具有 id 的元素...以上是关于观察目标节点上尚不存在的突变的主要内容,如果未能解决你的问题,请参考以下文章