Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript document.querySelector-inside MutationObserver:好的做法还是坏的做法? 目标和我的努力_Javascript_Asynchronous_Document Ready_Mutation Observers_Queryselector - Fatal编程技术网

Javascript document.querySelector-inside MutationObserver:好的做法还是坏的做法? 目标和我的努力

Javascript document.querySelector-inside MutationObserver:好的做法还是坏的做法? 目标和我的努力,javascript,asynchronous,document-ready,mutation-observers,queryselector,Javascript,Asynchronous,Document Ready,Mutation Observers,Queryselector,我试图获得一个方法,使其能够等到元素已经存在于DOM中。我读了几篇关于MutationObserver的文章,我得到了这个方法,它应该可以满足我的需要: const waitForElement = async (queryString) => { return new Promise((resolve) => { const observer = new MutationObserver((mutations) => { mutations

我试图获得一个方法,使其能够等到元素已经存在于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');
问题 问题是,它实际上没有按预期工作:
控制台.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
,但我至少可以避免这种情况。(也没有理由在实际使用的范围之上的范围中声明
元素
,而“查询字符串”在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,
        });
    });
};

有选择地接受一个元素也可能是有意义的,这样您就可以停止等待该元素,让它以一些适当的“取消”错误被拒绝。

Oh!我懂了!那太好了!我已经按照您的建议实现了
rootElement
,并更正了变量声明。我将搜索如何实现你提到的中止信号,那太好了!非常感谢你!看见