Можно ли реагировать на элементы, добавляемые в DOM, до того, как событие загрузки документа будет запущено в Javascript?

Я пытаюсь сделать вставку javascript, которая будет манипулировать страницей по мере ее загрузки. Сценарий находится в заголовке, и я хочу, чтобы он мог манипулировать элементом, как только он будет найден с помощью document.querySelector. Другими словами, он должен реагировать на изменения в DOM, пока document.readyState является «интерактивным», прежде чем он будет «загружен». Я не могу использовать тайм-аут/интервал, потому что загрузка документа блокируется до тех пор, пока не будет загружен весь документ, поэтому, если я поставлю тайм-аут 0 мс, он не будет выполняться до тех пор, пока document.readyState не будет «загружен».

Существуют ли какие-либо события, которые срабатывают при добавлении элементов в DOM? Я попробовал DOMNodeInserted, но, похоже, он срабатывает только для элементов, добавленных асинхронно после загрузки документа.

Наконец, это должно быть выполнено только с помощью javascript; У меня нет доступа к html или серверу. Вставка идет на чужие сайты.


person Spevak    schedule 09.07.2015    source источник
comment
Сценарий, размещенный в конце документа, будет запущен до первого «рендеринга», но после создания всех элементов. Поскольку это новая загрузка страницы, можно предположить, что все текущие элементы были только что «добавлены», что может быть полезным подходом.   -  person user2864740    schedule 10.07.2015
comment
Возможно, вы захотите взглянуть на веб-компоненты.   -  person Bergi    schedule 10.07.2015


Ответы (2)


Вы должны прикрепить события к самому документу, а затем проверить цель события и, если это то, что вам нужно, выполнить нужное действие. Например:

document.addEventListener("click", function(e){
  var element = e.target;
  if (element.nodeName === "A") {
    //I am gonna do something with <a> elements
    //Don't forget to return true if it is an anchor and you want the default event to trigger because if not, it will cancel the event.

  } else if (element.className.match("myClass")) {
    //OK, this element contains the class i am looking for, let's do something with it
  } else if (element.id === "myId") {
    //I finally found the element with the ID i was looking for
  }
});

Обновление (для вставки узлов):

document.addEventListener("DOMNodeInserted", function(e){
      // e is a MutationEvent
      var element = e.target;
      //Behavior here is pretty much the same as above
      if (element.nodeName === "A") {
        //I am gonna do something with <a> elements
        //Don't forget to return true if it is an anchor and you want the default event to trigger because if not, it will cancel the event.

      } else if (element.className.match("myClass")) {
        //OK, this element contains the class i am looking for, let's do something with it
      } else if (element.id === "myId") {
        //I finally found the element with the ID i was looking for
      }
    });

Еще одно обновление:

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

person Mindastic    schedule 09.07.2015
comment
Я хотел бы использовать этот подход, но не могу найти событие, которое срабатывает при первом добавлении элемента в DOM. - person Spevak; 10.07.2015
comment
Как я упоминал в исходном вопросе, я пробовал DOMNodeInserted, но у меня это не сработало. Мне не удалось зафиксировать какие-либо события DOMNodeInserted, пока документ загружался в первый раз. После загрузки DOM вставка новых узлов асинхронно запускает событие, но это не то, что я ищу. Мне нужно событие, которое срабатывает при загрузке исходных элементов DOM. - person Spevak; 10.07.2015
comment
Я думаю, что нашел возможное решение для вас. На основе этой ссылки (davidwalsh.name/detect-node-insertion) я создал следующее jsFiddle (jsfiddle.net/0y4jet4L), и, похоже, он работает (по крайней мере, с тем, что я тестировал). Это может быть не лучшим решением, но может помочь :) - person Mindastic; 10.07.2015
comment
Классная находка! После некоторых первоначальных тестов кажется, что даже с этим методом события обрабатываются после того, как document.readyState изменится на «complete». Но это кажется самым близким к тому, чего я пытаюсь достичь. Реагировать раньше, чем это, вероятно, невозможно. - person Spevak; 10.07.2015

Может быть, вы задаете неправильный вопрос? Почему бы не загрузить страницу с любой оболочкой или простым фреймом, который вам нужен, а затем использовать что-то вроде AngularJS для динамического рендеринга того, что вам нужно? Вам не обязательно нужен сервер для чего-то подобного.

person Rob    schedule 09.07.2015