QuerySelector не работает в коде расширения Chrome

Привет, я впервые использую JavaScript и HTML, поэтому, возможно, я делаю что-то не так:

Я пытаюсь вставить что-то новое на веб-страницу, используя расширение Chrome, и мой код иногда работает, а иногда нет. Например, когда я пытаюсь вставить текст на любую страницу YouTube, мой код может querySelect id="logo", но не id="secondary". У меня нет хорошего понимания JavaScript или HTML, и я полностью застрял здесь.

Вот мой manifest.json и мой content.js:

{
    "manifest_version": 3,
    "name": "tutorial",
    "version": "1.0",
    "description": "Add text to YouTube page",
    "content_scripts": [
      {
        "js": ["content.js"],
        "matches": [
          "https://www.youtube.com/*"
        ]
      }
    ]
}
if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded',afterDOMLoaded);
} else {
  console.info('DOM fully loaded and parsed');
  
  const object = document.querySelector('#secondary');

  if (object) {
    const newElement = document.createElement('div');
    newElement.innerText = 'Hello from the YouTube Element Injector!';
    object.insertAdjacentElement('afterbegin', newElement);
  } else {
    console.info('object is null');
  }
}

и мой результат с #лого

и мой результат с #secondary

Буду признателен за любой совет! Спасибо

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
1
66
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

С приведенным вами примером я предполагаю, что вы пытаетесь изучить DOM youtube.com. Узел #secondary кажется существует, но не во время первого рендеринга.

Может быть, вы можете попробовать подождать, пока readystate изменится

document.addEventListener("readystatechange", (event) => {
  if (document.readyState === "complete") {
    afterDOMLoaded(event);
  }
});

Вот документация MDN: https://developer.mozilla.org/en-US/docs/Web/API/Document/readystatechange_event

Спасибо за ваш совет, хотя это не было непосредственной причиной моей проблемы, это было ново и интересно узнать!

maiko 21.04.2023 19:24
Ответ принят как подходящий

Возможно, на странице YouTube не было «#secondary» во время выполнения вашего кода. Это может произойти, если элемент добавляется на страницу динамически после того, как ваш код уже запущен.

Вы можете обойти это, используя MutationObserver для отслеживания изменений в DOM.

// Define a function to handle DOM mutations
function handleMutations(mutationsList, observer) {
  for (const mutation of mutationsList) {
    if (mutation.type === 'childList') {
      const obj = document.querySelector('#secondary');

      if (obj) {
        const el = document.createElement('div');
        el.innerText = 'Hello from the YouTube Element Injector!';
        obj.insertAdjacentElement('afterbegin', el);
        // you should disconnect() after insertion for performance
        observer.disconnect();
      }
    }
  }
}

// Create a new observer and start watching for mutations
const observer = new MutationObserver(handleMutations);
observer.observe(document.body, { childList: true });

Это создает MutationObserver и начинает отслеживать изменения в document.body. Когда дочерний элемент был добавлен или удален (например, мутация «childList»), вызывается handleMutations. В этой функции вы можете попробовать выбрать #secondary и вставить новый элемент div.

Обратите внимание, что после вставки нового элемента вы должны вызыватьObserver.disconnect(), чтобы наблюдатель не мог следить за дальнейшими мутациями. Это связано с тем, что вам нужно вставить новый элемент только один раз, и вы не хотите вставлять его каждый раз при изменении DOM.

Надеюсь, это поможет! Дайте знать, если у вас появятся вопросы.

Спасибо, Патрик, это спасло мою проблему! Я добавил перерыв; внутри if (obj), чтобы выйти из цикла for, иначе он вставил новый элемент 4 раза :)

maiko 21.04.2023 19:20

Другие вопросы по теме