Обнаружить, что данный элемент был удален из DOM без ущерба для производительности - PullRequest
0 голосов
/ 17 мая 2018

У меня есть такие:

const element = this.getElementById("victim")

function releaseKraken(targetElement) {}

Я хочу, чтобы функция вызывалась при удалении element из DOM.

Я могу представить что-то вроде этого:

element.onRemove(() => releaseKraken(element))

Я понимаю, что мне нужно MutationObserver, но вся документация, которую я нашел, фокусируется на наблюдении за дочерними элементами данного элемента, тогда как мне нужно наблюдать за самим элементом.

UPD: вопрос Как обнаружить добавление / удаление элемента из элемента dom? фокусируется на наблюдении за детьми данного родителя. Я не хочу смотреть на детей или родителей. Я хочу получать уведомления, когда данный элемент удаляется из DOM. Не дети. И я не хочу устанавливать наблюдателя на родительском элементе данного элемента (если это не единственный вариант), потому что это повлияет на производительность.

UPD2: если я установлю MutationObserver на document, это приведет к тому, что обратный вызов будет срабатывать тысячи или даже миллионы раз за сеанс, и каждый раз, когда обратному вызову придется фильтровать огромный список удаленных элементов чтобы увидеть, если он содержит тот, о котором идет речь. Это просто безумие.

Мне нужно что-то простое, как я показал выше. Я хочу, чтобы обратный вызов был запущен ровно один раз: при удалении данного элемента.

Ответы [ 2 ]

0 голосов
/ 17 мая 2018

Как вы сказали, MutationObserver позволяет вам только обнаружить, когда манипулируют дочерними элементами элемента.Это означает, что вам нужно будет прослушать родительский элемент и проверить, какие изменения были внесены, чтобы увидеть, был ли удален целевой элемент.

function onRemove(element, callback) {
  const parent = element.parentNode;
  if (!parent) throw new Error("The node must already be attached");

  const obs = new MutationObserver(mutations => {
    for (const mutation of mutations) {
      for (const el of mutation.removedNodes) {
        if (el === element) {
          obs.disconnect();
          callback();
        }
      }
    }
  });
  obs.observe(parent, {
    childList: true,
  });
}

, а затем на вашем примере вместо

element.onRemove(() => releaseKraken(element));

Вы можете сделать

onRemove(element, () => releaseKraken(element));

Этот подход должен быть достаточно быстрым, если все, что вы делаете, это наблюдаете за одним элементом.Хотя это может показаться приличным количеством циклов, для removedNodes довольно редко быть более одного узла, и если что-то не удаляет тонны братьев и сестер за раз, mutations тоже будет довольно маленьким.

Вы также можете подумать о

callback(el);

, который позволит вам сделать

onRemove(element, releaseKraken);
0 голосов
/ 17 мая 2018

Вот решение, которое я нашел на этой странице

document.getElementById("delete_one_div").addEventListener('click', function() {
  var divToDelete = document.getElementsByTagName("div")[0];
  divToDelete.parentNode.removeChild(divToDelete);
});

var element = document.getElementById("div_to_be_watched")
var in_dom = document.body.contains(element);
var observer = new MutationObserver(function(mutations) {
  if (in_dom && !document.body.contains(element)) {
    console.log("I was just removed");
    in_dom = false;
    observer.disconnect();
  }

});
observer.observe(document.body, { childList: true });
<div id="test">Test</div>
<div id="div_to_be_watched">Div to be watched</div>
<div class="div_to_be_watched">Second test</div>
<button id="delete_one_div">Delete one div</button>

EDIT

Я немного отредактировал фрагмент. У вас есть два варианта:

  1. Используйте это так, как есть. И это не очень потребляет память, так как условие if не очень сложно (только для проверки, содержит ли тело элемент), и оно наблюдает только до момента удаления и затем останавливается,
  2. Заставить наблюдателя наблюдать только определенный элемент для ограничения триггеров событий.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...