如何检测页面何时完成水化?

问题描述 投票:0回答:1

我正在尝试制作一个 chrome 扩展,它将向 React Web 应用程序注入内容脚本。虽然我成功地注入了代码,但页面的延迟Hydration经常会覆盖脚本所做的更改。

可以通过设置任意超时来在一定程度上避免这个问题,但这几乎不能算是解决方案,因为水合速度以及所需的时间因设备而异。

有没有办法检测页面何时完成水合作用,最好是通过承诺,以便我可以在之后对页面进行更改?

附注我已经尝试过

customeElements.whenDefined()
但 DevTools 一直告诉我
customElements
未定义。

javascript google-chrome-extension hydration
1个回答
0
投票

我提出的一个潜在解决方案涉及使用 MutationObserver 来监视 DOM 更改并将其与去抖函数结合起来。这个想法是,如果在指定的时间范围内(例如 1 秒)没有检测到任何变化,则水合作用可能已完成。

示例:

  const delay = 100;
  let debounceTimeout: NodeJS.Timeout;

  const timeoutCallback = () => {
    observer.disconnect(); // Stop observing
    console.log("Hydration probably completed.");
    // execute your code here
  };

  const observer = new MutationObserver((mutations, obs) => {
    console.log("Mutation observed", mutations, obs);
    clearTimeout(debounceTimeout);

    debounceTimeout = setTimeout(timeoutCallback, delay); // No mutations have occurred for the specified delay;
  });

  debounceTimeout = setTimeout(timeoutCallback, delay); // if no mutations occur at all (e.g. if the page is already loaded)

  observer.observe(document.body, {
    subtree: true,
    childList: true,
    attributes: false, // DO NOT set this to true because your page could have some dynamic component with some cool css animation written in react, and then you will get infinite amount of calls
  });

或者您可以将其移至单独的功能 像这样

export function observeDomStabilization(
  cb: () => void,
  {
    delay = 100,
    observeTarget,
    observeConfig,
  }: {
    delay?: number;
    observeTarget: Node;
    observeConfig: MutationObserverInit;
  }
) {
  let debounceTimeout: NodeJS.Timeout;

  const timeoutCallback = () => {
    observer.disconnect(); // Stop observing
    cb(); // Execute callback
  };

  const observer = new MutationObserver((mutations, obs) => {
    console.log("Mutation observed", mutations, obs);
    clearTimeout(debounceTimeout);

    debounceTimeout = setTimeout(timeoutCallback, delay); // No mutations have occurred for the specified delay;
  });

  debounceTimeout = setTimeout(timeoutCallback, delay); // if no mutations occur at all

  observer.observe(observeTarget, observeConfig);
}

然后像这样使用它

observeDomStabilization(
      async () => {
        console.log("Hydration likely completed.");

        // mount some cool apps or inject dom elements
      },
      {
        delay: 100,
        observeTarget: document.body,
        observeConfig: {
          childList: true,
          subtree: true,
        },
      }
    );

我不确定这是否是最好的解决方案,但至少它有效(我希望如此)

© www.soinside.com 2019 - 2024. All rights reserved.