Как в observer следить за определёнными объектами?
Есть вот такая конструкция:
<div class="wrap">
<div class="adv">...</div>
<div class="coup">...</div>
<div class="news">...</div>
<div class="coup">...</div>
<div class="adv">...</div>
<div class="coup">...</div>
</div>
Содержимое всех блоков меняется. Подскажите, как следить только за блоками с классом coup? Я нашла в интернете статью https://developer.mozilla.org/ru/docs/Web/API/MutationObserver/MutationObserver и там есть callback, но я так и не поняла, как его заполнить:
***
switch(mutation.type) {
case 'childList':
/* One or more children have been added to and/or removed
from the tree; see mutation.addedNodes and
mutation.removedNodes */
break;
***
Я предположила, что должна разместить после case "childList": классы, которые мне нужны. Я попыталась сделать так: case 'childList': [".coup"] но ничего не вышло. Или я ошибаюсь и это не та статья? Подскажите, как следить только за определёнными элементами?
Ответы (1 шт):
Возможны два варианта выборочного мониторинга:
- подключить обсервер только к интересующим нас элементам,
- подключить обсервер к общему предку и проверять в обработчике значение параметра mutation.target
Приведу пример для первого варианта:
function callback(mutationList, observer) {
mutationList.forEach((mutation) => {
switch (mutation.type) {
case 'childList':
log(`изменилась структура элемента .${mutation.target.className}`)
break
case 'attributes':
log(`изменились атрибуты элемента .${mutation.target.className}`)
break
}
})
}
const options = {
childList: true,
attributes: true,
subtree: true // на всю глубину (false - только один уровень иерархии)
}
const observer = new MutationObserver(callback)
document.querySelectorAll(".coup").forEach(el =>
observer.observe(el, options))
// дальше пошла мишура для демонстрации
document.querySelector('#add-to-coup').addEventListener('click', e => {
document.querySelectorAll('.coup').forEach(el => {
const child = document.createElement('div')
child.innerHTML = '-- coup\'s child'
el.appendChild(child)
})
})
document.querySelector('#add-to-adv').addEventListener('click', e => {
document.querySelectorAll('.adv').forEach(el => {
const child = document.createElement('div')
child.innerHTML = '-- adv\'s child'
el.appendChild(child)
})
})
document.querySelector('#change-coup').addEventListener('click', e => {
document.querySelectorAll('.coup').forEach(el => {
el.style.color = el.style.color === 'red' ? 'inherit' : 'red'
})
})
document.querySelector('#change-adv').addEventListener('click', e => {
document.querySelectorAll('.adv').forEach(el => {
el.style.color = el.style.color === 'red' ? 'inherit' : 'red'
})
})
function log(msg) {
const item = document.createElement('li')
item.innerHTML = msg
document.querySelector('#log').appendChild(item)
}
<button id="add-to-adv">добавить к .adv</button>
<button id="add-to-coup">добавить к .coup</button>
<button id="change-adv">изменить .adv</button>
<button id="change-coup">изменить .coup</button>
<ol style="width: 80vw; height: 100px; overflow-y: scroll;" id="log"></ol>
<div class="wrap">
<div class="adv">adv</div>
<div class="coup">coup</div>
<div class="news">news</div>
<div class="coup">coup</div>
<div class="adv">adv</div>
<div class="coup">coup</div>
</div>
Конкретные изменения (что именно добавлено или удалено) передаются в обработчик через свойства параметра mutation addedNodes и deletedNodes.
Вот пример их использования:
function callback(mutationList, observer) {
mutationList.forEach((mutation) => {
switch (mutation.type) {
case 'childList':
mutation.addedNodes.forEach(el => {
if (el.className === 'coup') {
log('добавлен .coup')
}
})
break
case 'attributes':
break
}
})
}
const options = {
childList: true,
attributes: false,
subtree: false
}
const observer = new MutationObserver(callback)
observer.observe(document.querySelector(".wrap"), options)
document.querySelector('#add-new-coup').addEventListener('click', e => {
const child = document.createElement('div')
child.className = 'coup'
child.innerHTML = 'new coup'
document.querySelector('.wrap').appendChild(child)
})
document.querySelector('#add-new-adv').addEventListener('click', e => {
const child = document.createElement('div')
child.className = 'adv'
child.innerHTML = 'new adv'
document.querySelector('.wrap').appendChild(child)
})
function log(msg) {
const item = document.createElement('li')
item.innerHTML = msg
document.querySelector('#log').appendChild(item)
}
<button id="add-new-adv">добавить новый .adv</button>
<button id="add-new-coup">добавить новый .coup</button>
<ol style="width: 80vw; height: 100px; overflow-y: scroll;" id="log"></ol>
<div class="wrap">
<div class="adv">adv</div>
<div class="coup">coup</div>
<div class="news">news</div>
</div>