javascript - MutationObserver 中的 document.querySelector:好还是坏的做法?
问题描述
目标和我尝试过的
我正在尝试获得一种能够等到元素已经在 DOM 中的方法。我已经阅读了一些关于 的文章MutationObserver
,并且我得到了这个方法,它应该可以完成我所需要的:
const waitForElement = async (queryString) => {
return new Promise((resolve) => {
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
const nodes = Array.from(mutation.addedNodes);
nodes.forEach((node) => {
console.log('NODE CUSTOM', node);
if (node.matches && node.matches(queryString)) {
observer.disconnect();
resolve(node);
}
});
});
});
observer.observe(document.documentElement, {
childList: true,
subtree: true,
});
});
};
然后,我可以简单地这样使用它:
await waitForElement('#id-of-element');
问题
问题是它实际上没有按预期工作:console.log
唯一记录“父母”元素,如果要搜索的元素在树的深处,似乎没有记录它(这正在用于更复杂的应用程序,所以它可能与异步调用等有关)。
问题
但是,我发现,我不需要通过突变和节点数组,而只需要查看实际元素是否在 DOM 中,所以我实现了这个:
const waitForElement = async (queryString) => {
return new Promise((resolve) => {
let element;
const observer = new MutationObserver(() => {
element = document.querySelector(queryString);
if (element) {
observer.disconnect();
resolve(element);
}
});
observer.observe(document.documentElement, {
childList: true,
subtree: true,
});
});
};
这种方法将只检查,在每次突变之后,元素是否真的在使用该querySelector
方法的 DOM 上。它确实有效(另一个失败了),我发现它更容易阅读和理解,并且中间的循环更少。
这是一个值得推荐的方法吗?它会影响性能,还是与第一种方法相同?
谢谢!
解决方案
对选择器的单个查询应该非常、非常、非常快,所以我不认为这是一个问题,但这在很大程度上取决于您使用它的 DOM。测试您的用例以查看是否你发现一个性能问题。
我至少可以指定在 DOM 中查看的位置,而不是在每次更改时都查看整个内容。这最大限度地减少了对您的突变观察者的调用,并最大限度地减少了它在调用时所做的搜索量。如果一个特定的用例必须查看整个事情,那么它可以使用documentElement
,但我至少可以避免这种情况。(也没有理由element
在实际使用范围之上的范围内声明,并且“查询字符串”在 Web 编程中具有特定含义,这不是您在这里使用的,所以我只使用“选择器”或“选择器字符串”。)
以下是您如何做到这一点的想法:
const waitForElement = async (selector, rootElement = document.documentElement) => {
return new Promise((resolve) => {
const observer = new MutationObserver(() => {
const element = document.querySelector(selector);
if (element) {
observer.disconnect();
resolve(element);
}
});
observer.observe(rootElement, {
childList: true,
subtree: true,
});
});
};
可选地接受一个也可能是有意义的,AbortSignal
这样你就可以停止等待元素,让它拒绝一些适当的“取消”错误。
推荐阅读
- postgresql - postgreSQL 已关闭,但 pg_checksums 仍然说必须关闭集群
- ms-word - 如何在 MS Word 参考书目中显示 ISBN
- c# - Quartz C# 不同的类
- sql-server - Entity Framework 5 或 6 是否支持 SQL Server 同义词?
- linux - Git pathspecs linux(wsl)和windows之间的行为差异
- python - python中的条件切片
- java - 列表上的 Java 分页
- python - Python-检测点击最小化按钮
- javascript - 如何在对象中调用 this 类?
- ruby-on-rails - Rails:Paypal 端点 /v2/checkout/orders 返回 http 401