
Modern programlamada, ne olarak bilinen şey hakkında çok fazla katılım ve tartışma vardır. durum, en yaygın olarak kullanıcı etkileşimi etrafında döner. bu Mutasyon Gözlemcisi kullanıcı etkileşimine tepki vermek için kullanabileceğimiz için bu konuda bize yardımcı olabilecek güçlü bir API’dir. Mirasın yerini alan şey bu Mutasyon Olayları DOM3 Events spesifikasyonundan API.
Oluşturmak için MutationObserver
ile somutlaştırmamız gerekiyor new
şöyle bir geri arama ile birlikte anahtar kelime:
const observer = new MutationObserver(function onMutation(mutations, observer) {
console.log('Mutations', mutations)
})
bu onMutation
geri arama, aşağıda (sırasıyla) belirtildiği gibi iki argüman alır:
- Mutasyonlar – Bir liste Mutasyon Kaydı nesneler
- Gözlemci –
MutationObserver
bu inşa edildi. En son örneğimizde,observer
değişken.
bu onMutation
DOM düğümlerinde her değişiklik veya mutasyon olduğunda geri arama başlatılır. observe
yöntem.
bu observe
yöntem, ilk argümanı olarak “dinlemek” için bir DOM öğesini ve ikinci argümanı olarak bir seçenekler nesnesini alır:
const container = document.getElementById('root')
const options = { childList: true }
observer.observe(container, options)
DOM düğümünde herhangi bir değişiklik olduğunda, geri arama başlatılır ve bir liste alır. MutationRecord
nesneleri içeren ilk argümanı olarak tip meydana gelen mutasyon ve ne olduğu hakkında ek bilgi. Kullanıcı deneyiminde düzgün iyileştirmeler geliştirmek için kullanabileceğimiz bu kayıt nesneleridir.
Örneğin, bir öğeyi gözlemlemeye başlayabilir ve çocukları eklediğimizde, çıkardığımızda ve hatta başka çocuklarla değiştirdiğimizde haberdar olabiliriz, ancak bu bilgiyi ileterek istemek zorundayız. childList: true
içinde seçenekler argüman:
const observer = new MutationObserver(function onMutation(mutations, observer) {
console.log('Mutations', mutations)
})
observer.observe(root, {
childList: true,
})
const textarea = document.createElement('textarea')
const select = document.createElement('select')
root.appendChild(textarea)
root.replaceChild(select, textarea)
Başka bilgiler de isteyebiliriz. Geçebileceğimiz seçeneklerin tam listesi:
const observer = new MutationObserver(function onMutation(mutations, observer) {
console.log('Mutations', mutations)
})
observer.observe(root, {
attributes: true,
attributeOldValue: true,
attributeFilter: [],
childList: true,
characterData: true,
characterDataOldValue: true,
subtree: false,
})
istediğimizde attributes
ve bir özniteliğin değeri değiştirildiyse, bir önceki değeri değiştirilmeden önce girerek gözlemleyebiliyoruz. attributeOldValue: true
şöyle:
observer.observe(root, {
attributes: true,
attributeOldValue: true,
})
root.style.visibility = 'hidden'
root.style.visibility = 'visible'
bu attributeFilter
seçeneği, umursamadığımız mutasyonları filtrelemek için kullanılır. Mantıksal olarak, uygulama ne kadar büyükse, bu o kadar arzu edilir hale gelir, aksi takdirde, büyük olasılıkla o gözlemcide asla ilişkilendirmeyeceğimiz bir dizi değişiklik için hızlı bir şekilde çağrı yapabiliriz:
root.hidden = true
root.hidden = false
root.id = 'myid123'
root.id = 'yourid345'
root.title = 'root-document'
root.title = 'Root document'
root.onclick = () => {}
root.tabIndex = 1
root.option = 'f'
const someHttpRequest = async () => {
const res = await fetch('https://www.google.com')
return res.text()
}
someHttpRequest().then((text) => {
const span = document.createElement('span')
span.innerHTML += text.substring(0, 100)
root.dataset.something = span.innerHTML
root.style.backgroundColor = 'red'
})
Yalnızca ne zaman bildirim almayı umursarsak hidden
ve title
değişiklikler, bunu filtre seçeneğine koyabiliriz:
observer.observe(root, {
attributes: true,
attributeOldValue: true,
attributeFilter: ['hidden', 'title'],
})
Bu, sonuçları azaltır ve geri çağırma uygulamasında onu filtrelememiz gerekmeyecektir (bu, işlev bloğunu şişirecek ve gelecekte kodumuzu korumayı zorlaştıracaktır):
ayarladığımızda subtree: true
seçeneklerde, gözlemlenen öğenin tüm alt öğelerinde meydana gelen değişikliklerden haberdar oluruz:
observer.observe(root, {
attributes: true,
attributeOldValue: true,
subtree: true,
})
someHttpRequest().then((text) => {
const span = document.createElement('span')
span.innerHTML += text.substring(0, 100)
root.dataset.something = span.innerHTML
root.style.backgroundColor = 'red'
})
const form = document.createElement('form')
const input = document.createElement('input')
const select = document.createElement('select')
root.appendChild(form)
form.appendChild(input)
form.appendChild(select)
const options = ['100', '200', '300']
options.forEach((value) => {
const option = document.createElement('option')
select.appendChild(option)
option.text = value
option.value = value
option.style.color = 'red'
option.style.position = 'relative'
})
select.selectedIndex = 0
eğer ayarlarsak characterData
true olarak, aşağıdaki gibi öğelerin içindeki metin içeriği değişikliklerinden haberdar olabiliriz:
observer.observe(root, {
characterData: true,
characterDataOldValue: true,
subtree: true,
})
const root = document.createElement('root')
const form = document.createElement('form')
const select = document.createElement('select')
const selectLabel = document.createTextNode('Select an option')
const br = document.createElement('br')
const label = document.createElement('label')
label.appendChild(selectLabel)
root.appendChild(form)
form.append(br)
form.appendChild(selectLabel)
form.appendChild(select)
const options = ['100', '200', '300']
options.forEach((value) => {
const option = document.createElement('option')
select.appendChild(option)
option.value = value
option.text = value
option.style.color = 'red'
option.style.position = 'relative'
})
select.selectedIndex = 0
select.onchange = (e) => (selectLabel.data = `You selected: ${e.target.value}`)
Şimdi, seçeneklerin seçilmesi, gözlemcideki geri aramamızı arayacaktır:
Not: characterData
seçeneği, yalnızca metin içeriği değiştiğinde bizi bilgilendirecektir. Metin düğüm.
Yani bunun yerine:
const elem = document.createElement('div')
root.appendChild(elem)
elem.innerHTML = ''
elem.innerHTML = 'hello'
bir oluşturmalıyız Text
düğümü ve metnini üzerine ayarlayın data
bu geri aramayı tetikler:
const elem = document.createElement('div')
const textNode = document.createTextNode('')
elem.appendChild(textNode)
root.appendChild(elem)
textNode.data = 'hello'
Artık nasıl olduğuna dair temel bir anlayışa sahip olduğunuza göre, MutationObserver
çalışır, kullanıcı deneyimini geliştirmek için onu kullanan bir şeyi hızlı bir şekilde oluşturalım!
Kullanıcıların profil sayfalarını özelleştirmelerine olanak tanıyan bir sayfa oluşturduğumuzu varsayalım. Onlara görsel yapıya karar vermeleri için kutu ekleme seçeneği veriyoruz ve şuna benziyor:
Stil sayfasını, DOM yapısını ve JavaScript’i ( MutationObserver
henüz kodda yok):
Stil sayfası:
.grid {
display: flex;
}
.grid-item {
flex-grow: 1;
background-color: rgba(0, 0, 0, 0.2);
margin: 3px;
padding: 2px;
border-radius: 5px;
height: 150px;
border: 1px solid rgba(50, 20, 255, 0.8);
}
HTML:
<div id="root">
<div class="grid"></div>
<button id="add">Add box</button>
</div>
JavaScript:
const grids = []
const root = document.getElementById('root')
const addBtn = document.getElementById('add')
function createGrid() {
const grid = document.createElement('div')
root.appendChild(grid)
grid.classList.add('grid')
grids.push(grid)
return grid
}
function createGridBox(tagName, attrs) {
const elem = document.createElement(tagName)
elem.classList.add('grid-item')
if (attrs !== null && typeof attr === 'object') {
Object.entries(attrs).forEach(([attr, value]) => {
if (attr === 'style') {
Object.entries(value).forEach(([styleKey, styleValue]) => {
elem.style[styleKey] = styleValue
})
} else {
elem[attr] = value
}
})
}
return elem
}
function getMostRecentGrid() {
if (grids.length === 1) return grids[0]
if (grids.length > 1) return grids[grids.length - 1]
return null
}
addBtn.addEventListener('click', function onClick(e) {
let box = createGridBox('div')
let grid = getMostRecentGrid() || createGrid()
if (grid.children.length >= 3) {
grid = createGrid()
}
grid.appendChild(box)
})
Şimdi butona tıkladığımızda ve kutular göründüğünde, nereden başlayacağımız konusunda biraz kafamız karışmış, hatta hangi kutuya odaklanmamız gerektiği konusunda biraz kaybolmuş hissediyoruz. Kullanıcıya az önce ekledikleri kutuya bakmaları gerektiğini bildirmek için en son kutuya bir vurgu ekleyerek bunu düzeltebiliriz. Daha sonra normal bir uygulamanın yaptığı gibi girişler, seçimler vb. Gibi kontroller ekleyebiliriz.
En yeni kutuyu vurgulamak, kullanıcıya en yeni kutunun aktif kutu olduğunu işaret etmek, her kutuya bakmak ve nereden başlayacağını şaşırmış hissetmek yerine kullanıcıyı ona yönlendirmek anlamına gelir:
kolayca kullanabiliriz MutationObserver
Kutuları sayfaya eklenirken dinamik olarak vurgulamak (ve hatta vurgulamayı kaldırmak) için.
Böylece, daha iyi bir kullanıcı deneyimini geliştirmek için bir adım daha ileri gitmek için önceki örneğe ekleyebiliriz. MutationObserver
api.
Önce aktif kutu için sınıf adı stilini ekleyelim:
.focused-grid-item {
border: 1px solid magenta;
}
Daha sonra, sınıf adını eklendikçe kutulara eklemek/kaldırmak için bazı yardımcı işlevler oluşturabiliriz:
const isActive = (elem) => elem.classList.contains('focused-grid-item')
const highlight = (elem) =>
!isActive(elem) && elem.classList.add('focused-grid-item')
const unhighlight = (elem) =>
isActive(elem) && elem.classList.remove('focused-grid-item')
Şimdi geliyor MutationObserver
kurtarmak için!
const observer = new MutationObserver(function onMutation(mutations, observer) {
const lastMutation =
mutations.length > 1 ? mutations[mutations.length - 1] : mutations[0]
const { addedNodes, previousSibling, target } = lastMutation
if (previousSibling) {
unhighlight(addedNodes.item(0).previousElementSibling)
highlight(addedNodes.item(0))
} else {
if (
target.previousElementSibling &&
target.previousElementSibling.lastElementChild
) {
unhighlight(target.previousElementSibling.lastElementChild)
}
highlight(addedNodes.item(0))
}
})
const options = { childList: true, subtree: true }
observer.observe(root, options)
Geri aramada, meydana gelen son mutasyonu alır, böylece en yeni eleman. Tüm ihtiyacımız olan bu MutationRecord
içerdiği için target
bizi doğrudan DOM öğesine götüren özellik. Bu DOM öğesi şunları içerir: previousSibling
Odaklanmış stili ondan çıkarmak için erişmemiz gereken.
Şimdi çağrının döndürülen API’sini gözden geçirelim. new MutationObserver
içimizde bize döner observer
değişken:
const observer = new MutationObserver(function onMutation(mutations, observer) {...})
bu MutationObserver
3 yöntem döndürür observer
kullanabilirsiniz. biz çoktan geçtik observe
yöntem:
disconnect()
observe()
takeRecords()
bu disconnect
yöntem kaldırır observer
mutasyonlardan daha fazla bildirim almaktan. Bu, uygulamanın kalan ömrü boyunca sessiz kalacağı anlamına gelir. observe
tekrar bildirim almak için başka bir DOM öğesinde çağrılır.
bu takeRecords
yöntem, mutasyonların geri kalanını alır (bir liste MutationRecord
örnekler) ve bunları bir dizi olarak döndürür.
Çözüm
bu MutationObserver
içeren güçlü bir api’dir. MutationEvent
şimdi olan api kullanımdan kaldırıldı.
İle MutationObserver
DOM ile çalışmayı ve talep üzerine meydana gelen değişikliklere tepki vermeyi kolaylaştırır. Bu, onu Google Chrome gibi tarayıcılar için web uzantıları geliştirmek için harika bir yol arkadaşı yapar.
Ve bu, bu yazının sonunu tamamlıyor! Umarım bunu değerli bulmuşsunuzdur ve gelecekte daha fazlasını ararsınız!