Summary - Advanced DOM
Build a lazy-loaded image component using IntersectionObserver and custom elements.
Summary - Advanced DOM
In this group you learned four modern DOM APIs:
- MutationObserver: watches DOM node and attribute changes
- IntersectionObserver: reports how an element intersects the viewport
- ResizeObserver: notifies when an element's size changes
- Custom elements and Shadow DOM: build your own tags and isolated components
All four are callback based; they start with observe and end with disconnect. Shadow DOM starts with attachShadow.
Exercise Lazy loader: stop when visible
Create an IntersectionObserver. The callback takes entries; for each entry, if isIntersecting is true, log to console and stop watching that element with observer.unobserve. Set threshold to 0.
Show example solution
1. Create with new IntersectionObserver((entries) => {...}).
2. For each entry, if isIntersecting, log and call observer.unobserve(entry.target).
3. Set { threshold: 0 }.
Example solution:
const observer = new IntersectionObserver((entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
console.log('loaded');
observer.unobserve(entry.target);
}
}
}, { threshold: 0 });
Good habits
A few things to keep in mind when using these APIs:
- Always call
disconnectwhen done; it prevents memory leaks. - Use one observer for many elements; do not create a new one per element.
- Do not do heavy work inside the callback; just update the DOM.
- In Shadow DOM, bind styles to the component with the
:hostselector.
These habits matter in large apps.
Exercise Custom element with shadow DOM
Define a custom element named my-card. The class should extend HTMLElement. In connectedCallback, attach a shadow root in open mode with this.attachShadow. Finally register it with customElements.define.
Show example solution
1. Write a MyCard class that extends HTMLElement.
2. In connectedCallback, attach a shadow root with this.attachShadow({ mode: 'open' }).
3. Register it with customElements.define as 'my-card'.
Example solution:
class MyCard extends HTMLElement {
connectedCallback() {
const root = this.attachShadow({ mode: 'open' });
root.innerHTML = '<p>Hello</p>';
}
}
customElements.define('my-card', MyCard);
Test yourself
-
Match APIs to use cases
- MutationObserver
- Node added
- IntersectionObserver
- Entering viewport
- ResizeObserver
- Size change
- Shadow DOM
- Style isolation
-
Which method stops an observer?
- disconnect
- observe
- stop
- remove
Show answer
disconnect — Correct. disconnect stops watching and frees memory.