12-bo‘lim
DOM bilan tanishuv
DOM nima, elementlarni tanlash usullari, matn va HTML o'qish, atributlar va klasslar bilan ishlash.
Ushbu bo‘lim mundarijasi
Shu paytgacha kod konsolda ishladi. Endi sahifaning o'zini boshqarishni boshlaymiz.
DOM nima? #
Brauzer HTML ni o'qib, uni obyektlar daraxtiga aylantiradi. Bu daraxt - DOM (Document Object Model).
Sinov sahifasi #
Bu bo'limdagi misollar quyidagi HTML bilan ishlaydi:
<div id="ilova">
<h1 class="sarlavha">Vazifalar</h1>
<ul id="royxat">
<li class="vazifa bajarilgan" data-id="1">Non olish</li>
<li class="vazifa" data-id="2">Kitob o'qish</li>
<li class="vazifa" data-id="3">Sport bilan shug'ullanish</li>
</ul>
<button id="qoshish" disabled>Qo'shish</button>
</div>
// Misollarni sinash uchun DOM ni kod bilan quramiz
document.body.innerHTML = `
<div id="ilova">
<h1 class="sarlavha">Vazifalar</h1>
<ul id="royxat">
<li class="vazifa bajarilgan" data-id="1">Non olish</li>
<li class="vazifa" data-id="2">Kitob o'qish</li>
<li class="vazifa" data-id="3">Sport bilan shug'ullanish</li>
</ul>
<button id="qoshish" disabled>Qo'shish</button>
</div>`;
Elementlarni tanlash #
const royxat = document.getElementById("royxat");
const sarlavha = document.querySelector(".sarlavha");
const birinchiVazifa = document.querySelector(".vazifa");
const hammaVazifa = document.querySelectorAll(".vazifa");
console.log("getElementById :", royxat.tagName);
console.log("querySelector :", sarlavha.textContent);
console.log("Birinchi vazifa :", birinchiVazifa.textContent);
console.log("Nechta vazifa :", hammaVazifa.length);
console.log("Topilmasa :", document.querySelector(".yoq"));
getElementById : UL
querySelector : Vazifalar
Birinchi vazifa : Non olish
Nechta vazifa : 3
Topilmasa : null
querySelector - CSS selektorlarining to'liq kuchiquerySelector va querySelectorAll istalgan CSS selektorini
qabul qiladi:
document.querySelector("#royxat li:first-child");
document.querySelector(".vazifa:not(.bajarilgan)");
document.querySelectorAll("li[data-id='2']");
document.querySelectorAll("ul > li.vazifa");
Eski metodlar ham bor, lekin ular kamroq moslashuvchan:
| Metod | Qaytaradi | Izoh |
|---|---|---|
getElementById | Bitta element | Eng tez, lekin faqat id |
getElementsByClassName | Jonli to'plam | Avtomatik yangilanadi |
getElementsByTagName | Jonli to'plam | Avtomatik yangilanadi |
querySelector | Bitta element yoki null | Har qanday selektor |
querySelectorAll | Statik ro'yxat | Har qanday selektor |
Zamonaviy kodda deyarli har doim querySelector ishlatiladi.
Jonli va statik to'plam #
const jonli = document.getElementsByClassName("vazifa");
const statik = document.querySelectorAll(".vazifa");
console.log("Boshida jonli :", jonli.length);
console.log("Boshida statik:", statik.length);
// Yangi element qo'shamiz
const yangi = document.createElement("li");
yangi.className = "vazifa";
yangi.textContent = "Yangi vazifa";
document.getElementById("royxat").appendChild(yangi);
console.log("Qo'shgandan keyin jonli :", jonli.length);
console.log("Qo'shgandan keyin statik:", statik.length);
Boshida jonli : 3
Boshida statik: 3
Qo'shgandan keyin jonli : 4
Qo'shgandan keyin statik: 3
const elementlar = document.getElementsByClassName("vazifa");
for (let i = 0; i < elementlar.length; i++) {
const yangi = document.createElement("li");
yangi.className = "vazifa";
document.body.appendChild(yangi); // to'plam o'sib boradi!
}
elementlar.length har takrorlanishda oshadi - sikl hech
qachon tugamaydi va sahifa muzlaydi.
Xuddi shu muammo element o'chirganda ham bo'ladi:
// NOTO'G'RI - to'plam qisqaradi, indeks o'tib ketadi
for (let i = 0; i < jonli.length; i++) {
jonli[i].remove(); // yarmi qoladi
}
Yechim - querySelectorAll ishlating (statik ro'yxat), yoki
jonli to'plamni massivga aylantiring:
const massiv = [...document.getElementsByClassName("vazifa")];
querySelectorAll natijasi forEach ni qo'llab-quvvatlaydi,
lekin map/filter uchun uni ham massivga aylantirish kerak:
[...document.querySelectorAll(".vazifa")].map((e) => e.textContent);
Matn va HTML o'qish #
const element = document.querySelector(".sarlavha");
console.log("textContent :", element.textContent);
console.log("innerHTML :", element.innerHTML);
const royxat = document.getElementById("royxat");
console.log("innerHTML uzunligi:", royxat.innerHTML.length > 50);
console.log("textContent da teg bormi?:", royxat.textContent.includes("<li>"));
// innerText vs textContent
const yashirin = document.createElement("div");
yashirin.innerHTML = "Ko'rinadi <span style='display:none'>yashirin</span>";
document.body.appendChild(yashirin);
console.log("textContent :", JSON.stringify(yashirin.textContent));
console.log("innerText :", JSON.stringify(yashirin.innerText));
textContent : Vazifalar
innerHTML : Vazifalar
innerHTML uzunligi: true
textContent da teg bormi?: false
textContent : "Ko'rinadi yashirin"
innerText : "Ko'rinadi"
innerHTML bilan foydalanuvchi matnini yozmangelement.innerHTML = foydalanuvchiKiritgan; // XAVFLI
Agar foydalanuvchi shunday yozsa:
<img src=x onerror="alert('hujum')">
brauzer uni haqiqiy teg sifatida qo'shadi va onerror kodi
ishga tushadi. Bu XSS (Cross-Site Scripting) hujumi.
Xavfsiz variant - textContent:
element.textContent = foydalanuvchiKiritgan; // teglar matn bo'lib qoladi
Uch metodning farqi:
| Xossa | Nima qiladi | Xavfsizmi |
|---|---|---|
textContent | Faqat matn, teglarni belgi sifatida | Ha |
innerText | Faqat ko'rinadigan matn | Ha |
innerHTML | HTML sifatida tahlil qiladi | Yo'q |
innerText sekinroq - u brauzerni joylashuvni qayta
hisoblashga majbur qiladi. Katta ro'yxatlarda textContent
ishlating.
Atributlar #
const tugma = document.getElementById("qoshish");
const vazifa = document.querySelector(".vazifa");
console.log("getAttribute :", tugma.getAttribute("id"));
console.log("hasAttribute :", tugma.hasAttribute("disabled"));
console.log("Xossa orqali :", tugma.disabled);
tugma.disabled = false;
console.log("O'zgartirgandan keyin:", tugma.disabled);
// data-* atributlari
console.log("data-id :", vazifa.getAttribute("data-id"));
console.log("dataset orqali:", vazifa.dataset.id);
vazifa.dataset.holat = "faol";
console.log("Yangi data :", vazifa.getAttribute("data-holat"));
getAttribute : qoshish
hasAttribute : true
Xossa orqali : true
O'zgartirgandan keyin: false
data-id : 1
dataset orqali: 1
Yangi data : faol
Atribut - HTML da yozilgan matn. Xossa - DOM obyektidagi qiymat.
<input id="maydon" value="boshlangich">
const maydon = document.getElementById("maydon");
// Foydalanuvchi matnni o'zgartirdi
maydon.getAttribute("value"); // "boshlangich" - HTML dagi
maydon.value; // foydalanuvchi yozgani
Amaliy qoida:
| Maqsad | Nimani ishlating |
|---|---|
| Joriy holat | Xossa: .value, .checked, .disabled |
| Boshlang'ich qiymat | Atribut: getAttribute("value") |
| Maxsus ma'lumot | dataset: data-id → .dataset.id |
dataset nomlari camelCase ga aylanadi:
data-user-id -> dataset.userId
data-toliq-nom -> dataset.toliqNom
Klasslar bilan ishlash #
const vazifa = document.querySelector(".vazifa");
console.log("Boshida :", vazifa.className);
console.log("contains :", vazifa.classList.contains("bajarilgan"));
vazifa.classList.add("muhim");
console.log("add :", vazifa.className);
vazifa.classList.remove("bajarilgan");
console.log("remove :", vazifa.className);
vazifa.classList.toggle("tanlangan");
console.log("toggle :", vazifa.className);
vazifa.classList.toggle("tanlangan");
console.log("toggle 2 :", vazifa.className);
vazifa.classList.replace("muhim", "oddiy");
console.log("replace :", vazifa.className);
console.log("Klasslar soni:", vazifa.classList.length);
Boshida : vazifa bajarilgan
contains : true
add : vazifa bajarilgan muhim
remove : vazifa muhim
toggle : vazifa muhim tanlangan
toggle 2 : vazifa muhim
replace : vazifa oddiy
Klasslar soni: 2
className ni to'g'ridan-to'g'ri o'zgartirmangelement.className = "yangi"; // BARCHA klassni o'chiradi
element.className += " yangi"; // bo'shliqni unutish oson
Ikkinchi variant ham xavfli - element klasssiz bo'lsa natija
" yangi" (boshida bo'shliq bilan) bo'ladi.
classList ishlating - u har doim to'g'ri ishlaydi:
element.classList.add("yangi");
element.classList.add("bir", "ikki", "uch"); // bir nechta
element.classList.toggle("faol", shart); // shartga qarab
Oxirgi shakl juda qulay:
tugma.classList.toggle("bajarilgan", vazifa.tugallandi);
Bu if/else yozishdan qisqaroq va aniqroq.
Daraxt bo'ylab harakat #
const royxat = document.getElementById("royxat");
const ikkinchi = document.querySelectorAll(".vazifa")[1];
console.log("Ota element :", ikkinchi.parentElement.tagName);
console.log("Bolalar soni :", royxat.children.length);
console.log("Birinchi bola :", royxat.firstElementChild.dataset.id);
console.log("Oxirgi bola :", royxat.lastElementChild.dataset.id);
console.log("Oldingi qo'shni:", ikkinchi.previousElementSibling.dataset.id);
console.log("Keyingi qo'shni:", ikkinchi.nextElementSibling.dataset.id);
console.log("Eng yaqin ul :", ikkinchi.closest("ul").id);
console.log("Eng yaqin div :", ikkinchi.closest("#ilova").id);
console.log("matches :", ikkinchi.matches(".vazifa"));
Ota element : UL
Bolalar soni : 3
Birinchi bola : 1
Oxirgi bola : 3
Oldingi qo'shni: 1
Keyingi qo'shni: 3
Eng yaqin ul : royxat
Eng yaqin div : ilova
matches : true
closest - hodisalarda eng kerakli metodclosest(selektor) elementning o'zidan boshlab yuqoriga
qarab birinchi mos keladigan ajdodni topadi.
Bu 14-bo'limdagi hodisa delegatsiyasida asosiy vosita bo'ladi:
royxat.addEventListener("click", (hodisa) => {
const element = hodisa.target.closest(".vazifa");
if (element) {
console.log("Bosildi:", element.dataset.id);
}
});
Foydalanuvchi <li> ichidagi <span> yoki <b> ni bossa ham,
closest bizni kerakli <li> ga olib chiqadi.
Diqqat: childNodes va children farq qiladi:
| Xossa | Nimani qaytaradi |
|---|---|
children | Faqat elementlar |
childNodes | Elementlar va matn tugunlari |
HTML dagi bo'shliq va yangi qatorlar ham matn tuguni hisoblanadi,
shuning uchun deyarli har doim children kerak.
getElementByIdvaquerySelectorbilan bir elementni toping.querySelectorAllbilan barcha.vazifani sanang.- Jonli va statik to'plam farqini element qo'shib isbotlang.
textContentvainnerHTMLnatijasini solishtiring.innerHTMLnima uchun xavfli ekanini tushuntiring.datasetorqalidata-idni o'qing va yangisini qo'shing.classListningadd,remove,togglemetodlarini sinang.togglening ikkinchi argumentini shart bilan ishlating.parentElementvachildrenbilan daraxt bo'ylab yuring.closestbilan ichki elementdan<ul>gacha chiqing.
Xulosa #
- DOM - HTML ning obyektlar daraxti ko'rinishi.
querySelectoristalgan CSS selektorini qabul qiladi.getElementsByClassNamejonli,querySelectorAllstatik.- Jonli to'plam sikl ichida cheksizlikka olib kelishi mumkin.
textContentxavfsiz,innerHTMLXSS ga yo'l ochadi.innerTextfaqat ko'rinadigan matnni beradi, lekin sekinroq.- Atribut HTML dagi matn, xossa DOM dagi joriy qiymat.
- Maxsus ma'lumot uchun
dataset(data-*). - Klass uchun
classListishlating,classNameemas. classList.toggle(nom, shart)-if/elseo'rniga.closestyuqoriga qarab qidiradi - delegatsiyada asosiy.childrenfaqat elementlar,childNodesmatnni ham beradi.
Keyingi bo'limda DOM ni o'zgartirishni - element yaratish va o'chirishni o'rganamiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.