Why not to use setTimeOut
?
I used to use setTimeOut
to wait until the entire JS codes are loaded so I can change the DOM.
But setTimeOut
is unstable because JS loading time depends on browser type, internet speed and other factors. So how many seconds you should wait? It might work for your computer, but not for others...
What is MutationObserver
MutationObserver
is a useful api that can observe DOM changes, and it also supports IE11!
Basic Syntax - observer()
Here is a sample HTML -
<ul class='myList'>
<li>LCD writing board</li>
<li>Paper</li>
<li>
Tablet
<ul class='tabletList'>
<li>IPAD</li>
<li>Samsung Galaxy Tab </li>
</ul>
</li>
</ul>
//identity an element to observe
const myListObserver = document.querySelector(".myList");
//a callback that runs when the observer is triggered
const observer = new MutationObserver(function() {
console.log('trigged');
});
//passing element to observer function, and `options`
observer.observe(myListObserver, {OPTIONS_OBJECT});
Options
Object
Options
decides when to trigger the callback -
Options List -
let Options = {
childList: bool,
attributes: bool,
characterData: bool,
subtree: bool,
attributeFilter: array,
attributeOldValue: bool,
characterDataOldValue: bool,
}
Note: One of childList, attributes, and/or characterData must be true when you call observe().
1. Options - childList
observer.observe(myListObserver, {childList: true});
The callback is only triggered when immediate children nodes are added or removed.
In example HTML, if anything in .tabletList
(nested list) is changed, then it won't trigger the callback.
2. Options - subtree
observer.observe(myListObserver, {childList: true, subtree: true});
The callback will be triggered when any child nodes inside .myList
is added or removed.
3. Options - attributes
and attributeFilter
observer.observe(myListObserver, {attribute: true});
Execute callback when any attribute is changed
observer.observe(myListObserver, {attribute: true, attributeFilter:['class', 'style']});
Execute callback when class name or style is changed.
For example, if .tabeltList
changes name, then the callback will be triggered.
Here is the attributes list at w3schools.
4. Options - characterData
<ul class='myList'>
<li>LCD writing board</li>
<li>Paper</li>
<li>
Tablet
<ul class='tabletList'>
<li>IPAD</li>
<li>Samsung Galaxy Tab </li>
</ul>
</li>
</ul>
observer.observe(myListObserver, {childList: true, subtree: false, characterData: true});
It will execute callback if I change Paper
text.
observer.observe(myListObserver, {subtree: true, childList: false, characterData: true});
It will execute callback if I change IPAD
text.
5. Options - attributeOldValue
, characterDataOldValue
Set to true to record previous value so callback can use.
Note:attributes
will be automatically set to true if attributeOldValue
is true. characterData
and characterDataOldValue
are as same as the attribute
ones.
Callback
We can loop every element in mutations
const observer = new MutationObserver(function(mutations) {
for (let mutation of mutations) {
case 'childList':
break;
case 'attributes':
console.log(mutation.oldValue) //if attributeOldValue == true
break;
case: 'characterData':
console.log(mutation.oldValue) //if characterDataOldValue == true
break;
}
});
Using the disconnect() method
observer.disconnect();
Stop to watch for mutations.
If we don't use disconnect()
, then the watching will never stop, and might cause some memory problems.
Top comments (1)
ı like it thanks sweet girl