12-bo‘lim

DOM bilan tanishuv

DOM nima, elementlarni tanlash usullari, matn va HTML o'qish, atributlar va klasslar bilan ishlash.

🕑 16 daqiqa o‘qish 📄 689 so‘z 👁 1 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. DOM nima?
  2. Sinov sahifasi
  3. Elementlarni tanlash
  4. Jonli va statik to'plam
  5. Matn va HTML o'qish
  6. Atributlar
  7. Klasslar bilan ishlash
  8. Daraxt bo'ylab harakat
  9. Xulosa

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).

HTML dan DOM daraxtiga document html head body title h1 ul "Sarlavha" (matn) li, li, li Har bir teg - obyekt
JavaScript shu daraxtning har bir tugunini o'zgartira oladi

Sinov sahifasi #

Bu bo'limdagi misollar quyidagi HTML bilan ishlaydi:

HTML
<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>
JavaScript
// 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 #

JavaScript
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"));
Natija
getElementById  : UL
querySelector   : Vazifalar
Birinchi vazifa : Non olish
Nechta vazifa   : 3
Topilmasa       : null
querySelector - CSS selektorlarining to'liq kuchi

querySelector va querySelectorAll istalgan CSS selektorini qabul qiladi:

JavaScript
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:

MetodQaytaradiIzoh
getElementByIdBitta elementEng tez, lekin faqat id
getElementsByClassNameJonli to'plamAvtomatik yangilanadi
getElementsByTagNameJonli to'plamAvtomatik yangilanadi
querySelectorBitta element yoki nullHar qanday selektor
querySelectorAllStatik ro'yxatHar qanday selektor

Zamonaviy kodda deyarli har doim querySelector ishlatiladi.

Jonli va statik to'plam #

JavaScript
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);
Natija
Boshida jonli : 3
Boshida statik: 3
Qo'shgandan keyin jonli : 4
Qo'shgandan keyin statik: 3
Jonli to'plam sikl ichida cheksizlikka olib keladi
JavaScript
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:

JavaScript
// 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:

JavaScript
const massiv = [...document.getElementsByClassName("vazifa")];

querySelectorAll natijasi forEach ni qo'llab-quvvatlaydi, lekin map/filter uchun uni ham massivga aylantirish kerak:

JavaScript
[...document.querySelectorAll(".vazifa")].map((e) => e.textContent);

Matn va HTML o'qish #

JavaScript
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));
Natija
textContent : Vazifalar
innerHTML   : Vazifalar
innerHTML uzunligi: true
textContent da teg bormi?: false
textContent : "Ko'rinadi yashirin"
innerText   : "Ko'rinadi"
innerHTML bilan foydalanuvchi matnini yozmang
JavaScript
element.innerHTML = foydalanuvchiKiritgan;     // XAVFLI

Agar foydalanuvchi shunday yozsa:

Natija
<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:

JavaScript
element.textContent = foydalanuvchiKiritgan;   // teglar matn bo'lib qoladi

Uch metodning farqi:

XossaNima qiladiXavfsizmi
textContentFaqat matn, teglarni belgi sifatidaHa
innerTextFaqat ko'rinadigan matnHa
innerHTMLHTML sifatida tahlil qiladiYo'q

innerText sekinroq - u brauzerni joylashuvni qayta hisoblashga majbur qiladi. Katta ro'yxatlarda textContent ishlating.

Atributlar #

JavaScript
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"));
Natija
getAttribute : qoshish
hasAttribute : true
Xossa orqali : true
O'zgartirgandan keyin: false
data-id      : 1
dataset orqali: 1
Yangi data   : faol
Atribut va xossa - ikki xil narsa

Atribut - HTML da yozilgan matn. Xossa - DOM obyektidagi qiymat.

HTML
<input id="maydon" value="boshlangich">
JavaScript
const maydon = document.getElementById("maydon");

// Foydalanuvchi matnni o'zgartirdi
maydon.getAttribute("value");    // "boshlangich" - HTML dagi
maydon.value;                     // foydalanuvchi yozgani

Amaliy qoida:

MaqsadNimani ishlating
Joriy holatXossa: .value, .checked, .disabled
Boshlang'ich qiymatAtribut: getAttribute("value")
Maxsus ma'lumotdataset: data-id.dataset.id

dataset nomlari camelCase ga aylanadi:

Natija
data-user-id    ->  dataset.userId
data-toliq-nom  ->  dataset.toliqNom

Klasslar bilan ishlash #

JavaScript
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);
Natija
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'zgartirmang
JavaScript
element.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:

JavaScript
element.classList.add("yangi");
element.classList.add("bir", "ikki", "uch");     // bir nechta
element.classList.toggle("faol", shart);          // shartga qarab

Oxirgi shakl juda qulay:

JavaScript
tugma.classList.toggle("bajarilgan", vazifa.tugallandi);

Bu if/else yozishdan qisqaroq va aniqroq.

Daraxt bo'ylab harakat #

JavaScript
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"));
Natija
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 metod

closest(selektor) elementning o'zidan boshlab yuqoriga qarab birinchi mos keladigan ajdodni topadi.

Bu 14-bo'limdagi hodisa delegatsiyasida asosiy vosita bo'ladi:

JavaScript
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:

XossaNimani qaytaradi
childrenFaqat elementlar
childNodesElementlar va matn tugunlari

HTML dagi bo'shliq va yangi qatorlar ham matn tuguni hisoblanadi, shuning uchun deyarli har doim children kerak.

Amaliy topshiriq
  1. getElementById va querySelector bilan bir elementni toping.
  2. querySelectorAll bilan barcha .vazifa ni sanang.
  3. Jonli va statik to'plam farqini element qo'shib isbotlang.
  4. textContent va innerHTML natijasini solishtiring.
  5. innerHTML nima uchun xavfli ekanini tushuntiring.
  6. dataset orqali data-id ni o'qing va yangisini qo'shing.
  7. classList ning add, remove, toggle metodlarini sinang.
  8. toggle ning ikkinchi argumentini shart bilan ishlating.
  9. parentElement va children bilan daraxt bo'ylab yuring.
  10. closest bilan ichki elementdan <ul> gacha chiqing.

Xulosa #

  • DOM - HTML ning obyektlar daraxti ko'rinishi.
  • querySelector istalgan CSS selektorini qabul qiladi.
  • getElementsByClassName jonli, querySelectorAll statik.
  • Jonli to'plam sikl ichida cheksizlikka olib kelishi mumkin.
  • textContent xavfsiz, innerHTML XSS ga yo'l ochadi.
  • innerText faqat ko'rinadigan matnni beradi, lekin sekinroq.
  • Atribut HTML dagi matn, xossa DOM dagi joriy qiymat.
  • Maxsus ma'lumot uchun dataset (data-*).
  • Klass uchun classList ishlating, className emas.
  • classList.toggle(nom, shart) - if/else o'rniga.
  • closest yuqoriga qarab qidiradi - delegatsiyada asosiy.
  • children faqat elementlar, childNodes matnni ham beradi.

Keyingi bo'limda DOM ni o'zgartirishni - element yaratish va o'chirishni o'rganamiz.

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.