突变观察者找不到孩子 - 以及节点保持静态的问题

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

我正在尝试为 Airbnb 构建一个 chrome 扩展。目前我正在尝试将一个 div(反应)附加到每个

listingDiv
的子组件,因为 airbnb 在网格中呈现它们。

一般实现这个我:

  1. 抓取脚本执行时页面上存在的任何内容

  2. 脚本执行后立即附加一个 MutationObserver。

  3. getElementByClassName
    找到子组件(价格容器),我可以在其中附加我插入到带有扩展名的页面中的
    div

我遇到了很多问题,但通常是:

a) 当用变异观察器抓取一个元素时,该元素没有完全完成——有时子组件还没有被渲染。

b) 使用 setInterval 持续检查

listingDiv
表明该元素实际上是静态的,并且子组件永远不会附加到它。

c) 我不确定我使用 MutationObserver 的方法是否正确——有些元素在突变时似乎不会触发(可能是因为它们是静态的)。

这是我的代码(目前充满了一些调试片段):

import React from "react";
import { createRoot } from 'react-dom/client';

// //---Initiate content-background script communication channel---
// // content-script.js


// let myPort = chrome.runtime.connect({name:"port-from-cs"});
// myPort.postMessage({greeting: "hello from content script"});

// myPort.onMessage.addListener((m) => {
//   console.log("In content script, received message from background script: ");
//   console.log(m.greeting);
// });


//---Add 'request-flights-button' buttons to the page---



// const reactComponent = React.createElement('div');

function ReactComponent({idNumber}) {
  return (
    <div id={"MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM" + idNumber.toString()}>test rabm</div>
  )
}

//---Grab all the listings on a page and iterate to generate listing information for each---

//---Render the 'request-flights-button' button on each listing div---
function renderFlightPriceRequestButton(listingDiv: HTMLDivElement, extensionListingId: string): void {
  const listingPriceClassName = '_i5duul';

  const priceContainer = listingDiv.getElementsByClassName(listingPriceClassName)[0];
  if (priceContainer === undefined) {

    setInterval(() => {
    console.log(listingDiv)
    console.log(listingDiv.getElementsByClassName(listingPriceClassName))
    }, 1000)
  }

  const attachmentPoint = document.createElement('span');
  attachmentPoint.id = 'request-flights-button-' + extensionListingId;
  priceContainer.appendChild(attachmentPoint);
  createRoot(attachmentPoint).render(<ReactComponent idNumber={extensionListingId}/>);


};




const configForListings = { attributes: true, childList: true, subtree: true };

// Callback function to execute when mutations are observed
function observerCallBackFindListings(mutationsList: MutationRecord[]): void {
  const listingClassName = 'c4mnd7m';

    for(let mutation of mutationsList) {
      if (mutation.type === 'childList' && mutation.addedNodes.length > 0){

          mutation.addedNodes.forEach(node => {
            if(node instanceof Element){
              const candidateListingDivs = node.querySelectorAll('.' + listingClassName) as NodeListOf<HTMLDivElement>;

              if (candidateListingDivs.length > 0) {
                for (let candidateListingDiv of candidateListingDivs){
                  console.log('calling from observer')
                  const extensionListingId = grabExtensionListingId(candidateListingDiv);
                  renderFlightPriceRequestButton(candidateListingDiv, extensionListingId);
                };
              }
            }
          })
      }
    }
};

function grabExtensionListingId(listingDiv: HTMLDivElement): string {
  let listingId;

  try {
    const listingUrlMetaTag = listingDiv.querySelector('meta[itemprop="url"]') as HTMLMetaElement;
    const listingDivUrl = listingUrlMetaTag.getAttribute('content');

    listingId = listingDivUrl?.split('/')[2].slice(0, 8);
    
    if(listingId === undefined){
      throw new Error('listingId is undefined');
    } else {
      return listingId;
    }
  } catch (error) {
    console.log(error);
    return 'error';
  }
}

// Create an observer instance linked to the callback function
const observerFindListings = new MutationObserver(observerCallBackFindListings);


function findListings (){
  const listingClassName = 'c4mnd7m';
  const existingListingDivs = document.getElementsByClassName(listingClassName) as HTMLCollectionOf<HTMLDivElement>;

  for (const listingDiv of existingListingDivs){
    const extensionListingId = grabExtensionListingId(listingDiv);
    renderFlightPriceRequestButton(listingDiv, extensionListingId);
  };

  observerFindListings.observe(document, configForListings);

}

findListings();





//---Send listing information on 'request-flights-button' button click---


//---Receive information from the background script---


//---Display flight information on the page---
javascript reactjs typescript mutation-observers
© www.soinside.com 2019 - 2024. All rights reserved.