The DOM, making the page actually do something
The DOM (Document Object Model) is the tree of HTML elements your browser shows. JavaScript can read it, change it, and listen to it. Before React and Vue, this was how every interactive site worked. Even with frameworks, you still hit the DOM eventually.
This lesson is short on purpose. The DOM API is huge, but you only need a handful of methods to do real work.
Finding elements
const btn = document.querySelector('#submit');
const items = document.querySelectorAll('.cart-item');querySelectorreturns the first match using a CSS selector, ornull.querySelectorAllreturns a NodeList of all matches. Loop it withforEach.getElementById,getElementsByClassNamestill exist. The query selector duo replaced them in most code.
Listening to events
btn.addEventListener('click', (event) => {
console.log('clicked', event.target);
});The callback receives an event object. Useful properties: event.target (the element clicked), event.preventDefault() (stop default behaviour like form submit), event.key (for keyboard events).
To stop listening, use removeEventListener with the same function reference. Anonymous arrow functions cannot be removed, so name them if you need to.
Creating and inserting elements
const li = document.createElement('li');
li.textContent = 'Masala Dosa';
li.classList.add('menu-item');
document.querySelector('#menu').appendChild(li);createElement makes a detached element. Set text, classes, attributes, then append it to a parent. appendChild, prepend, before, after and replaceWith give you all the placement you need.
textContent vs innerHTML (read this twice)
textContentsets the text. HTML in the string is treated as plain characters. Safe.innerHTMLsets HTML. Tags are parsed and inserted. Powerful, and dangerous.
el.textContent = '<img src=x onerror=alert(1)>'; // shows the text
el.innerHTML = '<img src=x onerror=alert(1)>'; // runs the scriptIf you put user input through innerHTML without sanitising it, you have given attackers a Cross-Site Scripting (XSS) hole. Default to textContent. Use innerHTML only with content you fully control.
One leaked
innerHTMLwith user data is enough for an attacker to steal session cookies. Take this rule seriously.
Event delegation
Adding a listener to every row of a 500-item list is wasteful. Add one listener on the parent and check event.target instead.
document.querySelector('#cart').addEventListener('click', (e) => {
if (e.target.matches('.remove-btn')) {
e.target.closest('.item').remove();
}
});This is event delegation. One listener handles all current and future children. Faster, simpler, less memory.
Why React exists
The above is fine for small pages. For a Zomato-scale app with thousands of dynamic pieces, manually tracking which DOM nodes need updating gets brutal. React (and Vue and Svelte) let you describe what the UI should look like for a given state, and the framework does the DOM diff for you.
Frameworks are not magic. They are just very good at the boring DOM work you would otherwise do by hand.
Quick recap
querySelectorto find,addEventListenerto react,createElementplusappendChildto build.textContentis safe.innerHTMLis XSS-shaped if you are not careful.- One delegated listener beats a hundred small ones.
Last lesson: modules and what "ship to production" actually means.
Free tools you can use while you learn
Watching quietly. Tap me if you want a tip.
Try this (0 of 1 done)
- 1
Show that textContent is safer than innerHTML by trying to inject "<script>".
show answer
fakeEl.textContent = '<script>alert(1)</script>'; console.log(fakeEl.textContent); // renders as plain text, no script execution