2.16-bob: DOM — tanlash, o'zgartirish, CRUD, events, delegation, bubbling
2-QISM — JavaScript (0 dan chuqurgacha) · 16-mavzu
1. Kirish va motivatsiya
Bu — JavaScript'ni sahifaga ulovchi bob. Hozirgacha JS mantiqini (o'zgaruvchi, funksiya, massiv...) o'rgandik, lekin u sahifadan "ajralgan" edi. DOM — JS bilan HTML o'rtasidagi ko'prik: tugma bosilsa javob berish, ro'yxatga element qo'shish, matnni o'zgartirish — frontend'ning haqiqiy joni.
0.5-bobda DOM (Document Object Model — HTML'dan qurilgan daraxt) va renderingni ko'rdik. Endi JS bilan o'sha daraxtni boshqaramiz: element tanlash, o'zgartirish, yaratish/o'chirish (CRUD), va hodisalarga (events) javob berish.
O'xshatish: DOM — uyning ichki tuzilishi (xonalar, eshiklar). JS — elektrik: chiroqni yoqadi, eshikni ochadi, devorni bo'yaydi. DOM API — elektrikning asboblari. Statik HTML — yashab bo'lmaydigan bo'sh uy; DOM manipulyatsiyasi — uni jonli qiladi.
DOM — vanilla JS frontend'ning asosi. React (11) "Virtual DOM" bilan buni avtomatlashtiradi, lekin asosini bilish shart — React ham oxir-oqibat DOMni o'zgartiradi. Bu bob — interaktiv vebning yuragi.
2. Nazariya — chuqur tushuntirish
2.1. DOM nima (0.5 takror)
DOM — brauzer HTML'dan quradigan obyektlar daraxti 0.5-bob. Har HTML element — node (tugun); JS bu obyektlarni o'qiydi va o'zgartiradi:
document
└── html
└── body
├── h1 (matn: "Salom")
└── ul
├── li
└── lidocument — butun DOM'ning kirish nuqtasi (global obyekt — brauzerda).
2.2. Element tanlash (selecting)
// Eng ko'p ishlatiladigan (CSS selektorlar bilan — 1.2)
document.querySelector(".karta"); // BIRINCHi mos element (yoki null)
document.querySelectorAll("li"); // BARCHA mos (NodeList — massivga o'xshash)
document.getElementById("asosiy"); // id bo'yicha (eng tez)
// querySelector — CSS selektor 1.2-bob ishlatadi:
document.querySelector("#menu .havola.faol");
document.querySelector("input[type='email']");
querySelector— eng universal (CSS selektor — 1.2).nullqaytarishi mumkin (element yo'q bo'lsa) — tekshiring (2.1:?.).querySelectorAll— NodeList (massiv emas, lekinforEachbor; to'liq Array metodlari uchun[...nodeList]— 2.7).
2.3. Kontent va atributni o'zgartirish
const el = document.querySelector("#sarlavha");
// Matn/HTML
el.textContent = "Yangi matn"; // faqat matn (xavfsiz — XSS yo'q, 14)
el.innerHTML = "<b>Qalin</b>"; // HTML (XSS xavfi — ishonchsiz ma'lumotda ishlatma!)
// Atribut
el.setAttribute("href", "/yangi");
el.getAttribute("href");
el.id = "yangiId"; // ko'p atribut to'g'ridan-to'g'ri
el.src = "rasm.jpg";
// Class (1.2)
el.classList.add("faol");
el.classList.remove("yashirin");
el.classList.toggle("ochiq"); // bor bo'lsa olib tashlaydi, yo'q bo'lsa qo'shadi
el.classList.contains("faol"); // true/false
// Stil 1.2-bob — odatda class afzal
el.style.color = "red";
el.style.display = "none";
textContentvsinnerHTML:textContent— faqat matn (xavfsiz).innerHTML— HTML parse qiladi (XSS xavfi — foydalanuvchi kiritgan ma'lumotniinnerHTMLga qo'yma! 14-bob). Imkoni bo'lsatextContent.
2.4. Element yaratish va qo'shish (Create)
// 1) Yangi element yaratish
const li = document.createElement("li");
li.textContent = "Yangi element";
li.classList.add("item");
// 2) Daraxtga qo'shish
const ul = document.querySelector("ul");
ul.appendChild(li); // oxiriga
ul.prepend(li); // boshiga
el.before(yangiEl); // oldiga
el.after(yangiEl); // keyiniga
// Zamonaviy: insertAdjacentHTML (joylashuv bilan)
ul.insertAdjacentHTML("beforeend", "<li>Tez usul</li>");Performance 0.5-bob: tsiklda
appendChildni ko'p chaqirish — ko'p reflow 0.5-bob.DocumentFragmentbilan yig'ib, bir marta qo'shing (0.5-Misol 4).
2.5. O'qish, yangilash, o'chirish (Read, Update, Delete)
// Read — tanlab, xususiyatni o'qi (2.2, 2.3)
const matn = el.textContent;
const qiymat = document.querySelector("input").value; // input qiymati
// Update — o'zgartirish (2.3)
el.textContent = "Yangilangan";
// Delete — o'chirish
el.remove(); // o'zini o'chiradi
parent.removeChild(child); // eski usul2.5b. DOM bo'ylab harakat (traversal)
Bitta elementni tanlab 2.2-bob, undan qo'shnilariga o'tish mumkin — daraxt bo'ylab "yurish":
const el = document.querySelector("li");
// Yuqoriga (ota)
el.parentElement; // bevosita ota element
el.closest(".karta"); // eng yaqin mos ota (o'zidan boshlab — Misol 3)
// Pastga (bolalar)
el.children; // bola ELEMENTLAR (HTMLCollection)
el.firstElementChild; // birinchi bola
el.lastElementChild; // oxirgi bola
// Yon (qo'shni — sibling)
el.nextElementSibling; // keyingi qo'shni
el.previousElementSibling; // oldingi qo'shni
*Element*vs*Node*:parentElement/children/nextElementSibling— faqat elementlarni beradi (xavfsiz).parentNode/childNodes/nextSibling— matn va bo'shliqlarni (text node) ham qamraydi — odatda*Element*versiyasini ishlating.closest(2.9-delegation'da ko'p) — o'zidan boshlab yuqoriga eng yaqin mos ota'ni izlaydi.
2.6. Events (hodisalar) — addEventListener
Event — foydalanuvchi harakati (bosish, yozish, scroll) yoki tizim hodisasi. addEventListener bilan javob beramiz:
const tugma = document.querySelector("#btn");
tugma.addEventListener("click", (event) => {
// event — hodisa haqida ma'lumot (qaysi element, koordinata...)
console.log("Bosildi!", event.target);
});Mashhur eventlar:
| Event | Qachon |
|---|---|
click |
bosilganda |
input |
input qiymati o'zgarganda (har harf) |
change |
input o'zgarib, fokus ketganda |
submit |
forma yuborilganda (1.1) |
keydown/keyup |
klaviatura |
mouseenter/mouseleave |
sichqoncha ustiga/chetga |
DOMContentLoaded |
DOM tayyor bo'lganda (0.5) |
addEventListener— eng moslashuvchan: bir elementga ko'p listener,removeEventListenerbilan o'chirish mumkin.onclick=(HTML/property) o'rniga doim shu.
2.7. Event obyekti, preventDefault, stopPropagation
form.addEventListener("submit", (e) => {
e.preventDefault(); // brauzerning standart xulqini TO'XTATADI
// (submit'da sahifa yangilanishini to'xtatadi — SPA uchun zarur)
console.log(e.target); // hodisa yuz bergan element
});
el.addEventListener("click", (e) => {
e.stopPropagation(); // hodisaning yuqoriga "ko'tarilishini" to'xtatadi (2.8)
});e.preventDefault()— standart xulqni to'xtatadi (forma submit, havola o'tishi). SPA va validatsiyada zarur.e.target— hodisa yuz bergan aniq element.e.currentTarget— listener biriktirilgan element.
2.8. Event bubbling va capturing — propagation
Element ichida bossangiz, hodisa tarqaladi (propagation). Ikki faza:
CAPTURING (pastga): document ... target (kamdan-kam)
TARGET: hodisa yuz bergan element
BUBBLING (yuqoriga): target ... document (DEFAULT)// Default — BUBBLING (ichki tashqi, "pufakcha ko'tarilganday")
ichki.addEventListener("click", () => console.log("ichki"));
tashqi.addEventListener("click", () => console.log("tashqi"));
// ichki bosilsa: "ichki" "tashqi" (yuqoriga ko'tariladi — MDN)
// Capturing fazasini yoqish (kamdan-kam):
tashqi.addEventListener("click", fn, { capture: true });Bubbling — hodisa ichki elementdan tashqiga ketma-ket "ko'tariladi". Bu — keyingi (2.9) event delegationning asosi.
e.stopPropagation()buni to'xtatadi.
2.9. Event delegation — kuchli naqsh
Event delegation — ko'p bolaga alohida listener o'rniga, bitta listener'ni ota'ga qo'yish; bubbling 2.8-bob tufayli ota barcha bola hodisalarini "eshitadi":
// Har li uchun alohida listener (1000 li = 1000 listener — sekin)
document.querySelectorAll("li").forEach(li =>
li.addEventListener("click", ...)
);
// Bitta listener ota'da (delegation — MDN)
document.querySelector("ul").addEventListener("click", (e) => {
if (e.target.matches("li")) { // qaysi li bosildi? (e.target — 2.7)
console.log(e.target.textContent);
}
});Nega delegation kuchli: (1) bitta listener (xotira/tezlik — 0.1); (2) dinamik qo'shilgan elementlar ham ishlaydi (keyin qo'shilgan li uchun ham); (3) toza kod. Ro'yxat, jadval, dinamik UI uchun ideal.
3. Sintaksis — tez ma'lumotnoma
// Tanlash (2.2)
document.querySelector(sel) .querySelectorAll(sel) .getElementById(id)
// O'zgartirish (2.3)
el.textContent el.innerHTML el.value
el.classList.add/remove/toggle/contains(c)
el.setAttribute(n, v) el.style.prop
// CRUD (2.4, 2.5)
document.createElement(tag) parent.appendChild(el)
el.remove() el.insertAdjacentHTML(pos, html)
// Events (2.6–2.9)
el.addEventListener("click", (e) => { e.preventDefault(); e.target; })
parent.addEventListener("click", e => { if (e.target.matches(sel)) {} }) // delegation4. Batafsil kod namunalari
Misol 1 — Tanlash, o'zgartirish, class (2.2, 2.3)
const sarlavha = document.querySelector("#sarlavha");
sarlavha.textContent = "Yangi sarlavha"; // matn (xavfsiz — 2.3)
sarlavha.classList.add("katta", "markaz"); // class (1.2)
const tugma = document.querySelector(".tugma");
tugma.addEventListener("click", () => {
sarlavha.classList.toggle("yashirin"); // bosilganda yashir/ko'rsat
});Misol 2 — Forma va preventDefault (2.7)
const form = document.querySelector("#login");
form.addEventListener("submit", (e) => {
e.preventDefault(); // sahifa yangilanishini to'xtat (2.7)
const email = form.querySelector("#email").value.trim(); // (2.6)
const parol = form.querySelector("#parol").value;
if (!email.includes("@")) { // validatsiya (2.6)
document.querySelector("#xato").textContent = "Email noto'g'ri";
return;
}
console.log("Yuborildi:", { email, parol }); // (haqiqatda fetch — 2.11)
});Misol 3 — Dinamik ro'yxat (CRUD + delegation) (2.4, 2.9)
const ul = document.querySelector("#royxat");
const input = document.querySelector("#yangi");
// CREATE — element qo'shish (2.4)
function qosh(matn) {
const li = document.createElement("li");
li.textContent = matn;
li.insertAdjacentHTML("beforeend", ' <button class="ochir"></button>');
ul.appendChild(li);
}
// DELETE — delegation bilan (bitta listener — 2.9)
ul.addEventListener("click", (e) => {
if (e.target.matches(".ochir")) { // o'chir tugmasi bosildimi? (2.9)
e.target.closest("li").remove(); // ota li'ni o'chir (2.5)
}
});
document.querySelector("#qosh").addEventListener("click", () => {
if (input.value.trim()) { qosh(input.value.trim()); input.value = ""; }
});Misol 4 — Bubbling namoyishi (2.8)
document.querySelector(".tashqi").addEventListener("click", () => {
console.log("Tashqi (ota)");
});
document.querySelector(".ichki").addEventListener("click", (e) => {
console.log("Ichki (bola)");
// e.stopPropagation(); // bu yo'q bo'lsa, "Tashqi" ham chiqadi (bubbling — 2.8)
});
// .ichki bosilsa: "Ichki (bola)" "Tashqi (ota)" (yuqoriga ko'tariladi)5. To'g'ri va noto'g'ri holatlar
1) innerHTMLga ishonchsiz ma'lumot (XSS)
// foydalanuvchi kiritgan ma'lumot — XSS xavfi (2.3, 14)
el.innerHTML = foydalanuvchiKiritdi;
// textContent (xavfsiz)
el.textContent = foydalanuvchiKiritdi;2) Ko'p element uchun alohida listener (delegation o'rniga)
// 1000 listener (2.9)
items.forEach(i => i.addEventListener("click", ...));
// delegation — bitta listener ota'da
parent.addEventListener("click", e => { if (e.target.matches(".item")) {} });3) Element yo'qligini tekshirmaslik
// element yo'q bo'lsa null.textContent xato (2.2, 0.5)
document.querySelector("#yoq").textContent = "x";
// tekshir (2.1)
const el = document.querySelector("#yoq");
if (el) el.textContent = "x"; // yoki el?.4) Forma submit'da preventDefault unutish
// sahifa yangilanib ketadi (SPA buziladi — 2.7)
form.addEventListener("submit", () => { fetch(...); });
// preventDefault
form.addEventListener("submit", (e) => { e.preventDefault(); fetch(...); });6. Keng tarqalgan xatolar va yechimlari
Xato 1 — Cannot read properties of null (addEventListener)
Sababi: element topilmadi — JS DOMdan oldin ishladi 0.5-bob yoki selektor xato. Yechimi: defer/DOMContentLoaded 0.5-bob; selektorni tekshiring; null tekshiring 2.2-bob.
Xato 2 — Dinamik element'da listener ishlamaydi
Sababi: keyin qo'shilgan elementga eski listener tegmaydi. Yechimi: event delegation 2.9-bob — ota'da listener.
Xato 3 — Forma sahifani yangilab yuboradi
Sababi: preventDefault yo'q 2.7-bob. Yechimi: submit handler'da e.preventDefault().
Xato 4 — Hodisa kutilmaganda ikki marta ishlaydi
Sababi: listener ikki marta qo'shilgan yoki bubbling 2.8-bob tufayli. Yechimi: listener'ni bir marta qo'shing; kerak bo'lsa stopPropagation yoki { once: true }.
Xato 5 — this event handler'da kutilmagan (2.5)
Sababi: oddiy functionda this — element; arrow'da — tashqi 2.5-bob. Yechimi: elementga e.currentTarget/e.target ishlating (aniq).
7. Integratsiya — bu mavzu stack'ning qayerida uchraydi
- HTML/CSS (1.1, 1.2): DOM — HTML daraxti;
classList— CSS class. - Rendering 0.5-bob: DOM o'zgarish reflow/repaint; performance.
- Events + async 2.11-bob: click fetch DOMni yangila.
- Browser APIs 2.17-bob: localStorage bilan saqlash; DOM bilan birga.
- React (11): Virtual DOM — DOM manipulyatsiyasini avtomatlashtiradi; lekin asosi shu. JSX event (
onClick). - Forma (1.1, 11.10): submit, validatsiya,
value. - Xavfsizlik (14): XSS —
innerHTMLxavfi; sanitatsiya.
8. Eng yaxshi amaliyotlar (best practices)
querySelector(CSS selektor) ishlating; natijani null tekshiring 2.2-bob.textContent(xavfsiz),innerHTMLfaqat ishonchli ma'lumotda (XSS — 2.3, 14).- Event delegation — ko'p/dinamik element uchun bitta listener ota'da 2.9-bob.
addEventListener(HTMLonclickemas) — moslashuvchan, o'chirib bo'ladi 2.6-bob.- Forma submit'da
preventDefault2.7-bob. - DOM o'zgarishni yig'ing —
DocumentFragment, reflow kamaytiring (0.5, 2.4). - Class bilan stil (
classList),styleni kam (2.3, 1.2). - DOM tayyor bo'lganda ishla —
defer/DOMContentLoaded0.5-bob.
9. Amaliy loyiha: "Vazifalar Ro'yxati (To-Do App) — vanilla JS"
DOM'ning klassik loyihasi — hamma narsani birlashtiradi.
Maqsad
Element tanlash, CRUD, events, delegation, preventDefault va localStorage'ni 2.17-bob birlashtirib, to'liq interaktiv ilova qurish.
Talablar (requirements)
- HTML: input + "Qo'sh" tugma + ro'yxat (
ul) (1.1 semantik). - CREATE: forma submit'da (
preventDefault— 2.7) yangi vazifa qo'shing (createElement— 2.4); bo'sh kiritishda qo'shmang (validatsiya). - READ/render: vazifalarni massivda saqlang, DOMda ko'rsating (
mapg'oyasi — 2.7). - UPDATE: vazifani bossangiz "bajarilgan" (
classList.toggle— 2.3); ikki marta bossangiz tahrirlang (bonus). - DELETE: har vazifada "" tugma; delegation bilan o'chiring (Misol 3, 2.9).
- Filtr: "hammasi / bajarilgan / qolgan" tugmalari (
filter— 2.7). - Saqlash 2.17-bob:
localStorageda saqlang — sahifa yangilansa ham qolsin (JSON.stringify/parse— 2.8). - Hisoblagich: "Qolgan: N ta" (Array metodi — 2.7).
- Element yo'qligi tekshirilsin 2.2-bob; XSS yo'q (
textContent— 2.3).
Maslahatlar (hint)
- Holatni massivda tuting (
[{id, matn, bajarildi}]), har o'zgarishda DOMni qayta render qiling (React g'oyasi — 11). - Delegation:
ul.addEventListener("click", e => { if (e.target.matches(".ochir")) ... })2.9-bob. e.target.closest("li")— bosilgan tugmaning ota li'si 2.5-bob.- localStorage:
localStorage.setItem("vazifalar", JSON.stringify(arr))(2.17, 2.8). - ID uchun
Date.now()yoki hisoblagich (2.4-closure). - XSS:
li.textContent = vazifa.matn(innerHTML emas — 2.3).
"Tayyor" mezonlari (acceptance criteria)
- Vazifa qo'shish ishlaydi (forma + preventDefault).
- Bajarilgan holati toggle bilan; o'chirish delegation bilan.
- Filtr (hammasi/bajarilgan/qolgan) ishlaydi.
- localStorage'da saqlanadi (yangilansa ham qoladi).
- Qolgan vazifalar hisoblagichi to'g'ri.
- Bo'sh/noto'g'ri kiritish tekshirilgan.
-
textContent(XSS yo'q); element null tekshirilgan. - Bitta delegation listener (har li uchun alohida emas).
Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.
10. Xulosa va keyingi bobga ko'prik
Bu bobda JS'ni sahifaga ulovchi — DOMni o'rgandik:
- DOM — HTML'dan qurilgan obyektlar daraxti 0.5-bob;
document— kirish nuqtasi. - Tanlash:
querySelector/querySelectorAll/getElementById(CSS selektor — 1.2; null tekshirish). - O'zgartirish:
textContent(xavfsiz) vsinnerHTML(XSS — 14);classList;setAttribute. - CRUD:
createElement/appendChild/remove; reflow kamaytirish 0.5-bob. - Events:
addEventListener;e.preventDefault()/e.target; bubbling (yuqoriga); event delegation (bitta listener ota'da — ko'p/dinamik element uchun).
Keyingi bob — 2.17-bob: Browser APIs — localStorage, sessionStorage, fetch, Intersection Observer. DOM bilan sahifani o'zgartirdik; endi brauzer beradigan boshqa kuchli API'larni o'rganamiz: ma'lumotni brauzerda saqlash (localStorage), tarmoq (fetch — 2.11 takror), va element ko'rinishini kuzatish (Intersection Observer — lazy loading uchun).
Foydalanilgan rasmiy/ishonchli manbalar
- MDN Web Docs — Document Object Model,
querySelector, manipulating documents - MDN Web Docs —
addEventListener, Event bubbling, event delegation - MDN Web Docs —
Event.preventDefault/stopPropagation/target
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!