Mundarija (44)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Brauzer sahifani qanday quradi (Critical Rendering Path)
- 2.2. DOM nima — daraxt va Node turlari
- 2.3. DOM'ni o'qish va element tanlash (Read — querySelector oilasi)
- 2.4. DOM CRUD — yaratish, o'zgartirish, o'chirish
- 2.5. Atribut, class, style va dataset
- 2.6. Hodisalar (Events) — addEventListener, bubbling, delegation
- 2.7. Reflow va repaint — nega qo'lda DOM sekin
- 2.8. DocumentFragment va o'zgarishlarni to'plash (batching)
- 2.9. Imperativ DOM'ning fundamental muammosi (nega React kerak)
- 2.10. Declarative vs imperative — React falsafasiga ko'prik
- 2.11. DOM manipulyatsiyaning qolgan quroli: insertAdjacentHTML, cloneNode, replaceChild
- 2.12. BOM — Browser Object Model (window, location, history, navigator, screen)
- 2.13. localStorage, sessionStorage va sahifa hayot sikli (DOMContentLoaded vs load)
- 2.14. Fetch API — server bilan gaplashish (GET/POST/PUT/DELETE, async/await)
- 2.15. To'liq CRUD sikli: DOM + REST API birgalikda
- 3. Sintaksis — tez ma'lumotnoma
- 4. Batafsil kod namunalari
- Misol 1 — Element tanlash va xavfsiz o'qish (2.3)
- Misol 2 — DOM CRUD: yaratish, qo'shish, o'chirish (2.4)
- Misol 3 — innerHTML vs textContent va XSS xavfi (2.4, 14-QISM)
- Misol 4 — classList bilan holatni boshqarish (2.5)
- Misol 5 — Hodisalar va preventDefault (2.6)
- Misol 6 — Event delegation (1 listener, ko'p bola — 2.6)
- Misol 7 — DocumentFragment bilan tez ro'yxat qurish (2.8)
- Misol 8 — Layout thrashing va uni tuzatish (2.7)
- Misol 9 — To'liq imperativ "Vazifalar" ilovasi (2.9 og'rig'ini his qil)
- Misol 10 — Xuddi shu ilova React'da qanday ko'rinishini oldindan ko'rish (ko'prik)
- Misol 11 — insertAdjacentHTML, cloneNode va replaceWith (2.11)
- Misol 12 — localStorage bilan holatni saqlash (2.13)
- Misol 13 — Fetch bilan REST API: GET va POST, xato boshqaruvi (2.14)
- Misol 14 — To'liq CRUD: DOM + REST API + AbortController (2.14, 2.15)
- 5. To'g'ri va noto'g'ri holatlar
- 6. Keng tarqalgan xatolar va yechimlari
- 7. Integratsiya — bu mavzu stack'ning qayerida uchraydi
- 8. Eng yaxshi amaliyotlar (best practices)
- 9. Amaliy loyiha: "Vanilla DOM bilan Savatcha (imperativ)"
- Maqsad
- Talablar (requirements)
- Maslahatlar (hint)
- "Tayyor" mezonlari (acceptance criteria)
- 10. Xulosa va keyingi bobga ko'prik
- Foydalanilgan rasmiy/ishonchli manbalar
DOM API va CRUD — brauzerda HTML/CSS/JS takrori (11.1-bob)
11-QISM — Frontend: React · 1-mavzu
1. Kirish va motivatsiya
5–10 QISM'larda biz backend dunyosini chuqur o'rgandik: Node.js, API, ma'lumotlar bazasi, NestJS, arxitektura, DevOps. Backend — bu sahnaning orqasi (oshxona): ma'lumotni saqlaydi, hisoblaydi, qaytaradi. Endi 11-QISM'da sahnaning old tomoniga — foydalanuvchi ko'radigan va teginadigan qismga — frontendga o'tamiz. Bu — sizning kasbingdagi eng ko'zga ko'rinadigan, eng ko'p ish beriladigan va eng tez o'zgaradigan soha. Va uning markazida — React turadi.
Lekin React'ni o'rganishdan oldin bitta poydevorni tosh qotgan darajada mustahkam qilib olishimiz kerak: DOM (Document Object Model). Sababi oddiy va muhim — React aslida nima qiladi? U DOM bilan ishlashni avtomatlashtiradi. React'ni "sehrli" deb qabul qilsangiz, hech qachon chuqur tushunmaysiz; uni "men qo'lda qiladigan DOM ishlarini men o'rnimga, lekin aqlli qilib bajaradigan vosita" deb tushunsangiz — har bir hook, har bir key, har bir re-render sizga mantiqiy ko'rinadi. Shuning uchun bu bobda biz DOM'ni qo'lda (vanilla JS bilan) boshqaramiz — element yaratamiz, o'zgartiramiz, o'chiramiz (CRUD) — va eng muhimi, buning og'rig'ini his qilamiz. Aynan shu og'riq — React'ning butun mavjudligi sababi.
Bu bob 2.16-bob (DOM manipulyatsiya) va 0.5-bob (brauzer qanday ishlaydi)ning chuqurlashtirilgan, frontend rakursidan takrori: brauzer sahifani qanday quradi (critical rendering path — DOM, CSSOM, render tree, layout, paint), DOM daraxti va Node turlari, tanlash (querySelector oilasi), CRUD (createElement → append → update → remove), atribut/class/style/dataset, hodisalar (delegation, bubbling), reflow/repaint (nega qo'lda DOM sekin), DocumentFragment (batching), BOM (window/location/history), Web Storage (localStorage), Fetch API va to'liq CRUD sikli (server bilan GET/POST/PUT/DELETE — bobning "API (CRUD)" qismi), va eng muhimi — imperativ DOM'ning fundamental muammosi (UI ↔ state'ni qo'lda sinxron ushlab turishning iloji yo'qligi), bu bizni to'g'ri declarative yondashuvga — React'ga — olib keladi.
O'xshatish: DOM — bu jonli qo'g'irchoq teatri sahnasi. HTML — sahnaning boshlang'ich dekoratsiyasi (qo'g'irchoqlar qayerda turibdi). CSS — ularning kiyimi va yorug'lik. JavaScript esa — qo'g'irchoqchining iplari: har bir qo'g'irchoqning qo'lini, og'zini, joyini qo'lda tortib boshqarasiz. Kichik spektaklda (3 ta qo'g'irchoq) bu qiziq. Lekin 200 ta qo'g'irchoq bo'lsa-chi? Har biri ma'lumotga qarab o'zgarsa-chi (foydalanuvchi yozgan matn, server javobi)? Siz 200 ta ipni bir vaqtda, qo'lda, xatosiz tortib turolmaysiz — bittasini unutsangiz, sahna "yolg'on" ko'rsatadi (ma'lumot bir xil, ekran boshqacha). React — bu avtomat qo'g'irchoqchi: siz unga faqat "men sahna mana shunday ko'rinishini xohlayman" deb tasvirlaysiz, u esa qaysi ipni qachon tortishni o'zi hisoblab, eng kam harakat bilan bajaradi. Bu bobda biz iplarni qo'lda tortib ko'ramiz — keyingi bobda esa avtomatga o'tamiz.
Nega muhim?
- React'ning poydevori — React = aqlli DOM boshqaruvi; DOM'ni bilmasdan React "sehr" bo'lib qoladi.
- Og'riqni his qilish — imperativ DOM bilan kichik ilova yozsangiz, React'ning nega borligini hech qachon unutmaysiz.
- Debugging — brauzer, render, reflow tushunchasi performance va xatolarni tuzatishda hal qiluvchi 11.11-bob.
- Vanilla baza — ba'zan React kerak emas (oddiy sahifa, widget); DOM API'ni bilish — universal ko'nikma.
2. Nazariya — chuqur tushuntirish
2.1. Brauzer sahifani qanday quradi (Critical Rendering Path)
SIZ YUBORGAN: <html>...</html> + CSS + JS (matn — 0.4, 0.5)
BRAUZER BOSQICHMA-BOSQICH (Critical Rendering Path):
1. HTML ──parse──► DOM daraxti (Document Object Model — obyektlar daraxti)
2. CSS ──parse──► CSSOM daraxti (CSS Object Model — stillar daraxti)
3. DOM + CSSOM ──► RENDER TREE (ko'rinadigan elementlar + stillari)
(display:none — bu yerda YO'Q)
4. RENDER TREE ──► LAYOUT (reflow) (har element QAYERDA, qancha KATTA — geometriya)
5. LAYOUT ──────► PAINT (piksellar — rang, matn, chegara chiziladi)
6. PAINT ───────► COMPOSITE (qatlamlar birlashtiriladi → ekran)
┌──────┐ ┌───────┐ ┌────────────┐ ┌────────┐ ┌───────┐ ┌───────────┐
│ HTML │──►│ DOM │──►│ │──►│ LAYOUT │──►│ PAINT │──►│ COMPOSITE │
└──────┘ └───────┘ │ RENDER TREE│ └────────┘ └───────┘ └───────────┘
┌──────┐ ┌───────┐ │ │
│ CSS │──►│ CSSOM │──►│ │
└──────┘ └───────┘ └────────────┘
❗ JS DOM'ni o'zgartirsa → brauzer 4-6 bosqichni QAYTA bajaradi (reflow/repaint)Critical Rendering Path — brauzer matn (HTML/CSS) ni ekrandagi piksellarga aylantiradigan bosqichlar zanjiri. (1) HTML → DOM (obyektlar daraxti — 0.5); (2) CSS → CSSOM (stillar daraxti); (3) ikkalasi birlashib → render tree (faqat ko'rinadigan elementlar —
display:nonebu yerda yo'q); (4) layout/reflow (har element ekranda qayerda va qancha katta — geometriya hisoblanadi); (5) paint (piksellar — rang, matn, chegara chiziladi); (6) composite (qatlamlar birlashtiriladi → ekran). Eng muhim xulosa: JavaScript DOM'ni o'zgartirganda, brauzer layout/paint bosqichlarini qayta bajaradi (reflow/repaint — 2.7). Demak DOM bilan qanchalik ko'p va tartibsiz ishlasak, brauzer shunchalik ko'p qayta hisoblaydi — bu performance'ning asosiy manbai. React aynan shu qayta-hisoblashlarni minimallashtirish uchun yaratilgan.
2.2. DOM nima — daraxt va Node turlari
HTML matn: DOM daraxti (obyektlar):
<html> document
<body> └─ html (Element)
<h1>Salom</h1> └─ body (Element)
<ul> ├─ h1 (Element)
<li>Bir</li> │ └─ "Salom" (Text node)
<li>Ikki</li> └─ ul (Element)
</ul> ├─ li → "Bir" (Text)
</body> └─ li → "Ikki" (Text)
</html>
NODE TURLARI:
- Element node — teg (<div>, <li>) — eng ko'p ishlatiladigan
- Text node — teg ichidagi MATN ("Salom") — alohida node!
- Attribute — atribut (class="...", id="...")
- Comment, Document, DocumentFragment 2.8-bob
❗ document — kirish nuqtasi (butun daraxt ildizi, global obyekt)
❗ "Salom" matni — h1 ning ichidagi ALOHIDA text node (element emas)DOM (Document Object Model) — HTML hujjatning xotiradagi jonli obyektlar daraxti sifatidagi ko'rinishi. Brauzer HTML matnini o'qib, har bir tegni obyekt (node) ga aylantiradi va ularni ota-bola munosabatlari bilan daraxt qilib bog'laydi. Node turlari: Element (teg —
<div>,<li>— eng ko'p ishlatamiz), Text (teg ichidagi matn — diqqat: matn alohida node, elementning bir qismi emas), Attribute (atribut), Comment, Document.document— butun daraxtning ildizi va kirish nuqtasi (global obyekt — har doim shundan boshlaymiz). DOM "jonli" (live): JavaScript bu obyektlarni o'zgartirsa, brauzer ekranni yangilaydi. DOM — HTML faylning o'zi emas, balki uning brauzer xotirasidagi dasturlash interfeysi (API): JS shu API orqali sahifani o'qiydi va o'zgartiradi.
2.3. DOM'ni o'qish va element tanlash (Read — querySelector oilasi)
ZAMONAVIY (tavsiya — CSS selektor sintaksisi bilan):
document.querySelector(".card") → MOS kelgan BIRINCHI element (yoki null)
document.querySelectorAll("li") → BARCHA mos elementlar (NodeList)
element.querySelector(...) → faqat shu element ICHIDA qidiradi
ESKI / TEZ (bitta narsa uchun):
document.getElementById("app") → id bo'yicha (eng tez, # belgisiz)
document.getElementsByClassName("x") → jonli HTMLCollection (kam ishlatiladi)
document.getElementsByTagName("li") → jonli HTMLCollection
NAVIGATSIYA (qarindoshlarga o'tish):
el.parentElement el.children el.firstElementChild
el.nextElementSibling el.closest(".x") el.matches(".x")
❗ querySelector — null qaytarishi mumkin (element topilmasa) → tekshirish
❗ querySelectorAll → NodeList (massiv EMAS, lekin forEach bor; map yo'q)Element tanlash — DOM bilan har qanday ishning birinchi qadami (avval elementni "ushlab olamiz", keyin o'zgartiramiz). Zamonaviy va eng moslashuvchan usul —
querySelector(selector)(CSS selektor sintaksisi bilan birinchi mos elementni qaytaradi —.class,#id,div > p) vaquerySelectorAll(selector)(barcha mos elementlar — NodeList). Eski lekin tez usullar:getElementById(id bo'yicha —#belgisiz, eng tez),getElementsByClassName/TagName(jonli HTMLCollection). Navigatsiya:parentElement,children,nextElementSibling,closest(selector)(yuqoriga eng yaqin mosini topadi). Ikki tuzoq: (1)querySelectorelement topmasanullqaytaradi — to'g'ridan-to'g'ri.textContentqilsangizCannot read properties of nullxatosi (2.6 xatolar); (2)querySelectorAllnatijasi NodeList — massiv emas,forEachbor lekinmap/filteryo'q (kerak bo'lsa[...nodeList]yokiArray.frombilan massivga aylantiriladi — 2.7).
2.4. DOM CRUD — yaratish, o'zgartirish, o'chirish
CREATE (yaratish va daraxtga qo'shish):
const li = document.createElement("li"); // 1. element yarat (hali sahnada YO'Q)
li.textContent = "Yangi vazifa"; // 2. ichini to'ldir
ul.append(li); // 3. daraxtga ulash (endi ko'rinadi)
ul.prepend(li) // boshiga
el.before(node) / el.after(node) // yon tomoniga
READ (o'qish):
el.textContent // ichidagi MATN (xavfsiz — teg sifatida o'qimaydi)
el.innerHTML // ichidagi HTML (qulay, lekin XSS XAVFI — 2.5)
el.value // input/textarea qiymati (forma — 11.10)
UPDATE (o'zgartirish):
el.textContent = "..." el.classList.add("active") el.style.color = "red"
el.setAttribute("href","#") el.dataset.id = "5"
DELETE (o'chirish):
el.remove(); // o'zini o'chiradi (zamonaviy)
parent.removeChild(el); // eski usulDOM CRUD — element yaratish (Create), o'qish (Read), o'zgartirish (Update), o'chirish (Delete) — ya'ni sahifani dinamik boshqarishning to'rt amali. Create uch qadamli:
createElement(element yaratiladi, lekin hali daraxtda yo'q — ko'rinmaydi) → ichini to'ldirish →append(yokiprepend/before/after) bilan daraxtga ulash (endi ekranda paydo bo'ladi). Read:textContent(faqat matn — xavfsiz),innerHTML(HTML sifatida — qulay, lekin XSS xavfi — foydalanuvchi kiritgan matnni hech qachoninnerHTMLga qo'ymang — 14-QISM). Update:textContent,classList.add/remove/toggle,style,setAttribute,dataset. Delete:el.remove()(zamonaviy — element o'zini o'chiradi). Diqqat qiling: bu yerda biz har bir o'zgarishni qo'lda, qadam-baqadam aytyapmiz — "shu elementni yarat, shu yerga qo'sh, shu matnni o'zgartir". Bu imperativ uslub 2.10-bob. React'da esa biz faqat natijani tasvirlaymiz, qadamlarni emas.
2.5. Atribut, class, style va dataset
CLASS (eng ko'p — CSS bilan ishlash):
el.classList.add("active") el.classList.remove("active")
el.classList.toggle("open") el.classList.contains("active") // true/false
STYLE (to'g'ridan-to'g'ri — kam tavsiya, class afzal):
el.style.color = "red"; el.style.display = "none";
// camelCase: backgroundColor (background-color EMAS)
ATRIBUT:
el.setAttribute("href", "/home") el.getAttribute("href") el.removeAttribute("disabled")
el.id, el.href, el.src // ko'p atributlar to'g'ridan property sifatida ham
DATASET (data-* — o'z ma'lumotingizni elementga "yopishtirish"):
<li data-id="42" data-done="false">
el.dataset.id // "42" (data-id)
el.dataset.done // "false"
❗ class afzal style'dan (CSS'da turadi — ajratilgan, qayta ishlatiladi)
❗ dataset — DOM va JS ma'lumotini bog'lashning "qo'lbola" usuli (React'da kerak emas)Atribut/class/style/dataset — elementning ko'rinishi va ma'lumotini boshqarish vositalari.
classList— eng ko'p ishlatiladigan:add,remove,toggle(bor bo'lsa o'chir, yo'q bo'lsa qo'sh — switch tugmalar uchun ideal),contains.style— to'g'ridan-to'g'ri inline stil (lekin class afzalroq — stil CSS'da, ajratilgan turadi; xususiyatlar camelCase:backgroundColor,background-coloremas). Atribut:setAttribute/getAttribute/removeAttribute.dataset(data-*) — o'zingizning maxsus ma'lumotingizni HTML elementiga "yopishtirish" usuli (masalandata-id="42"→el.dataset.id).dataset— vanilla JS'da DOM elementi bilan JS ma'lumotini bog'lashning qo'lbola yechimi (qaysi tugma qaysi vazifaga tegishli?). Bu — imperativ DOM'ning yana bir og'rig'i: ma'lumot (JS obyekt) va ko'rinish (DOM element) alohida yashaydi, ularni sun'iy bog'lab turishga to'g'ri keladi. React'da ma'lumot va UI bitta joyda (komponent) yashaydi — bu muammo yo'qoladi.
2.6. Hodisalar (Events) — addEventListener, bubbling, delegation
HODISA TINGLASH:
button.addEventListener("click", (event) => {
event.target // hodisa SODIR BO'LGAN element
event.preventDefault() // brauzer standart xatti-harakatini to'xtat (forma submit, link)
event.stopPropagation() // bubbling'ni to'xtat
});
BUBBLING (ko'piklanish) — hodisa boladan OTAga ko'tariladi:
<ul> ← bu yerda ham "eshitiladi" (3)
<li> ← (2)
<button> ← bosildi (1) → yuqoriga ko'tariladi: button → li → ul → body
</ul>
EVENT DELEGATION (delegatsiya) — 1 ta listener bilan KO'P bolani boshqarish:
ul.addEventListener("click", (e) => {
if (e.target.matches(".delete-btn")) { /* o'chir */ } // qaysi bola bosildi?
});
// 100 ta tugmaga 100 ta listener O'RNIGA — 1 ta otaga (xotira/performance)Hodisalar — foydalanuvchi harakatlariga (click, input, submit, keydown...) javob berish mexanizmi.
addEventListener(turi, ishlovchi)— elementga hodisa tinglovchi biriktiradi; ishlovchi funksiyaeventobyektini oladi:event.target(hodisa sodir bo'lgan aniq element),event.preventDefault()(brauzer standart harakatini to'xtatadi — masalan forma yuborilib sahifa qayta yuklanishini — 11.10),event.stopPropagation(). Bubbling (ko'piklanish): hodisa boladan otaga ko'tariladi (button → li → ul → body) — shuning uchun otada tinglab, qaysi bola bosilganinievent.targetorqali bilish mumkin. Bu — event delegation (delegatsiya): 100 ta tugmaga 100 ta listener o'rniga 1 ta otaga listener qo'yib,e.target.matches(...)bilan ajratish (xotira va performance afzalligi — 2.16). React'da hodisalar boshqacha (synthetic events,onClickprop) — lekin asosida aynan shu bubbling/delegation mexanizmi yotadi (React barcha hodisalarni root'da delegatsiya qiladi). Demak bu tushuncha React'da ham hal qiluvchi.
2.7. Reflow va repaint — nega qo'lda DOM sekin
REPAINT (qayta bo'yash) — faqat KO'RINISH o'zgaradi (rang, ko'rinmaslik):
el.style.color = "red" → layout o'zgarmaydi, faqat qayta bo'yaladi (arzonroq)
REFLOW (layout qayta hisoblash) — GEOMETRIYA o'zgaradi (o'lcham, joy):
el.style.width = "200px" → brauzer BUTUN sahifa joylashuvini qayta hisoblaydi (QIMMAT!)
el.remove() el.append(...) el.offsetHeight (o'qish ham!)
❌ YOMON — tsiklda 1000 marta reflow (har iteratsiyada DOM'ga teginish):
for (let i = 0; i < 1000; i++) {
ul.innerHTML += `<li>${i}</li>`; // har safar: butun ul qayta quriladi + reflow
}
✅ YAXSHI — bir marta DOM'ga teginish (2.8 fragment yoki bir string):
let html = "";
for (let i = 0; i < 1000; i++) html += `<li>${i}</li>`;
ul.innerHTML = html; // 1 marta reflow
❗ Layout thrashing — o'qish/yozishni aralashtirish (read→write→read) ketma-ket reflowReflow va repaint — DOM o'zgarganda brauzer bajaradigan ikki xil qayta-hisoblash. Repaint (qayta bo'yash) — faqat ko'rinish o'zgarsa (rang,
visibility) — nisbatan arzon. Reflow (layout qayta hisoblash) — geometriya o'zgarsa (o'lcham, joylashuv, element qo'shish/o'chirish) — brauzer butun (yoki katta) sahifa joylashuvini qaytadan hisoblaydi — qimmat. Asosiy sahna: agar tsiklda 1000 marta DOM'ga tegsangiz (innerHTML +=yoki har iteratsiyadaappend), 1000 marta reflow bo'ladi — sahifa qotadi. Yechim — o'zgarishlarni to'plab, DOM'ga bir marta tegish (string to'plabinnerHTML, yoki DocumentFragment — 2.8). Yana bir tuzoq — layout thrashing: o'qish (offsetHeight) va yozishni ketma-ket aralashtirish brauzerni har safar reflow'ga majbur qiladi. Mana React'ning eng katta texnik sababi: React o'zgarishlarni Virtual DOM'da to'playdi, eng kam farqni hisoblaydi (diffing), va haqiqiy DOM'ga bir marta, eng optimal qilib qo'llaydi (12.2-bobda batafsil). Siz qo'lda qiladigan bu optimizatsiyalarni React avtomatik qiladi.
2.8. DocumentFragment va o'zgarishlarni to'plash (batching)
DOCUMENTFRAGMENT — "vaqtinchalik, ko'rinmas konteyner" (xotirada, sahnada YO'Q):
const fragment = document.createDocumentFragment(); // bo'sh, ko'rinmas idish
for (let i = 0; i < 100; i++) {
const li = document.createElement("li");
li.textContent = `Element ${i}`;
fragment.append(li); // fragmentga qo'shamiz — REFLOW YO'Q (sahnada emas)
}
ul.append(fragment); // 1 MARTA DOM'ga ulanadi → 1 marta reflow
┌─────────────────────────────────────────────────────────┐
│ 100 ta append to'g'ridan ul'ga → ~100 reflow (sekin) │
│ 100 ta append fragment'ga + 1 → 1 reflow (tez) ✅ │
└─────────────────────────────────────────────────────────┘
❗ fragment ul'ga qo'shilgach — BO'SHAYDI (bolalari ul'ga ko'chadi)DocumentFragment — DOM'ning "vaqtinchalik, ko'rinmas idishi": u xotirada yashaydi, lekin asosiy daraxtga ulanmagan, shuning uchun unga element qo'shganda reflow bo'lmaydi 2.7-bob. Strategiya: barcha yangi elementlarni avval fragmentga to'playmiz (reflow'siz), so'ng fragmentni bir marta haqiqiy DOM'ga ulaymiz → faqat bitta reflow. 100 ta elementni to'g'ridan-to'g'ri qo'shsak ~100 reflow; fragment orqali — 1 ta. Bu — vanilla JS'da performance'ning klassik usuli. Va bu — aynan React'ning ishlash printsipining qo'lbola modeli: React ham o'zgarishlarni "vaqtinchalik" joyda (Virtual DOM) to'playdi va haqiqiy DOM'ga eng kam, eng optimal yangilanish bilan qo'llaydi. Fragment'ni tushunsangiz — Virtual DOM'ning nega kerakligini allaqachon his qilgan bo'lasiz.
2.9. Imperativ DOM'ning fundamental muammosi (nega React kerak)
MUAMMO: ma'lumot (state) va ko'rinish (DOM) — IKKI ALOHIDA joyda yashaydi
→ ularni QO'LDA sinxron ushlab turish kerak (har o'zgarishda!)
Misol: savatda 3 mahsulot. Foydalanuvchi bittasini o'chirdi.
SIZ QO'LDA quyidagilarning HAMMASINI yangilashingiz kerak:
✏️ massivdan o'chir (ma'lumot)
✏️ <li> ni DOM'dan o'chir (ro'yxat)
✏️ "Jami: 3 ta" → "2 ta" (hisoblagich)
✏️ umumiy narxni qayta hisobla va yangila (summa)
✏️ savat bo'shasa "Bo'sh" xabarini ko'rsat (shart)
→ BITTASINI unutsangiz → UI YOLG'ON ko'rsatadi (ma'lumot 2 ta, ekran 3 ta)
→ Ilova o'sgani sayin bu sinxronlash EKSPONENSIAL murakkablashadi
→ Bu — frontend'dagi xatolarning eng katta MANBAI
❗ Muammo "DOM'ni qanday o'zgartirish" emas — "QAYSI joylarni o'zgartirishni
ESLAB qolish va HECH BIRINI o'tkazib yubormaslik"Imperativ DOM'ning tub muammosi — bu "DOM'ni o'zgartirish qiyin" emas (uni o'rgandik, oson). Asl muammo: ma'lumot (JS dagi massiv/obyekt — state) va uning ko'rinishi (DOM elementlari) ikki alohida dunyoda yashaydi, va har bir o'zgarishda siz ularni qo'lda, bir-biriga moslab yangilashing kerak. Savatdan bitta mahsulot o'chirilganda: massivdan o'chirasiz,
<li>ni o'chirasiz, "Jami" hisoblagichini yangilaysiz, narxni qayta hisoblaysiz, savat bo'shasa "Bo'sh" xabarini chiqarasiz — beshta joy, va bittasini unutsangiz UI yolg'on ko'rsatadi (ma'lumot bilan ekran bir-biriga mos kelmaydi). Ilova o'sgani sayin bu "sinxronlash" eksponensial murakkablashadi va frontend xatolarining eng katta manbai bo'ladi. Muammoning mohiyati — "qaysi joylarni yangilashni eslab qolish". Mana shu yerda React keladi: "Ma'lumotni o'zgartir, UI'ni MENGA qo'y".
2.10. Declarative vs imperative — React falsafasiga ko'prik
IMPERATIV (vanilla — "QANDAY qilish" — qadam-baqadam buyruq):
const li = document.createElement("li");
li.textContent = task.title;
li.classList.add("task");
ul.append(li);
counter.textContent = tasks.length;
// ... har o'zgarishda qaysi DOM'ni qanday yangilashni QO'LDA aytasiz
DEKLARATIV (React — "NIMA bo'lishini" — natijani tasvirlash):
function TaskList({ tasks }) {
return (
<>
<ul>{tasks.map(t => <li className="task">{t.title}</li>)}</ul>
<p>Jami: {tasks.length}</p>
</>
);
}
// "UI ma'lumotga qarab MANA SHUNDAY ko'rinadi" — qadamlarni React hisoblaydi
┌──────────────┬─────────────────────────┬──────────────────────────┐
│ │ IMPERATIV (vanilla) │ DEKLARATIV (React) │
├──────────────┼─────────────────────────┼──────────────────────────┤
│ Siz aytasiz │ HAR QADAMNI │ FAQAT NATIJANI │
│ Sinxronlash │ qo'lda (xato manbai) │ avtomatik (React) │
│ Fikrlash │ "DOM'ni qanday o'zgartira│ "UI ma'lumotning funksiyasi│
│ │ man?" │ UI = f(state)" │
└──────────────┴─────────────────────────┴──────────────────────────┘Imperativ va deklarativ — frontend'dagi ikki tafakkur uslubi. Imperativ (vanilla DOM — bu bobda o'rgandik): kompyuterga qanday qilishni qadam-baqadam buyurasiz ("element yarat, matnni qo'y, ro'yxatga qo'sh, hisoblagichni yangila..."). Deklarativ (React): natija qanday ko'rinishini tasvirlaysiz, qadamlarni hisoblashni vositaga qoldirasiz ("UI ma'lumotga qarab mana shunday ko'rinadi"). Eng muhim formula:
UI = f(state)— foydalanuvchi interfeysi ma'lumotning funksiyasi. Siz faqat ma'lumotni (state) o'zgartirasiz; React esa yangi UI'ni hisoblab, haqiqiy DOM'ni eng optimal tarzda yangilaydi (2.7, 2.8 dagi optimizatsiyalarni avtomatik qiladi). Bu — restoranga o'xshaydi: imperativ = oshpazga har bir harakatni aytib turish ("pichoqni ol, sabzini kes, tovaga sol..."); deklarativ = "menga osh kerak" deyish (qanday tayyorlashni oshpaz biladi). React'ni o'rganish — aslida bu yangi tafakkurga o'tish. Keyingi boblar shu g'oyani ochib beradi.
2.11. DOM manipulyatsiyaning qolgan quroli: insertAdjacentHTML, cloneNode, replaceChild
insertAdjacentHTML(pozitsiya, html) — HTML'ni ANIQ joyga qo'shish (innerHTML += dan tez):
"beforebegin" → elementning O'ZIDAN oldin
"afterbegin" → element ICHIga, boshiga
"beforeend" → element ICHIga, oxiriga (eng ko'p — append'ga o'xshash)
"afterend" → elementning O'ZIDAN keyin
ul.insertAdjacentHTML("beforeend", `<li>${xavfsizMatn}</li>`);
❗ innerHTML += butun konteynerni QAYTA quradi (eski listenerlar o'ladi);
insertAdjacent... mavjudini saqlab, faqat yangisini qo'shadi.
cloneNode(deep) — elementning NUSXASI:
const copy = tpl.cloneNode(true); // true = bolalari bilan chuqur nusxa
const copy = tpl.cloneNode(false); // false = faqat o'zi (bolasiz)
// <template> teg bilan birga — DOM shablonlarini takrorlashning tez usuli
replaceChild / replaceWith — bir elementni boshqasiga ALMASHTIRISH:
old.replaceWith(yangi); // zamonaviy (old o'rniga yangi turadi)
parent.replaceChild(yangi, old); // eski API (tartibga e'tibor: yangi, keyin eski)
❗ innerHTML — foydalanuvchi ma'lumoti bilan XAVFLI (XSS — 2.4). Ishonchli/statik
HTML uchungina; aks holda createElement + textContent yoki matnni ekranlash.Qolgan manipulyatsiya vositalari — CRUD'ning 2.4-bob kundalik bo'lmagan, ammo muhim to'ldiruvchilari.
insertAdjacentHTML(pozitsiya, html)— HTML matnini elementga aniq to'rt pozitsiyadan biriga (beforebegin,afterbegin,beforeend,afterend) joylaydi;innerHTML +=dan afzalligi shundaki, u konteynerni qaytadan qurmaydi (innerHTML +=esa butun ichki HTML'ni o'chirib qayta o'rnatadi — mavjud hodisa tinglovchilari yo'qoladi va reflow ortadi).cloneNode(deep)— element nusxasini oladi (true— bolalari bilan chuqur nusxa,false— faqat o'zi);<template>tegi bilan birga DOM shablonlarini tez takrorlashda ishlatiladi.replaceWith(zamonaviy) vareplaceChild(eski) — mavjud elementni boshqasi bilan almashtiradi.insertAdjacentHTMLhaminnerHTMLkabi HTML'ni bajaradi, shuning uchun foydalanuvchi kiritgan matn bilan XSS xavfi bir xil — faqat ishonchli/statik HTML uchun.
2.12. BOM — Browser Object Model (window, location, history, navigator, screen)
window — brauzer oynasi = GLOBAL obyekt (barcha global o'zgaruvchi/funksiya shunda):
window.innerWidth / innerHeight // ko'rinadigan oyna o'lchami (px)
window.setTimeout / setInterval // vaqt bo'yicha kod (aslida window.metodi)
window.alert / confirm / prompt // brauzer dialoglari
location — joriy URL (o'qish VA o'zgartirish):
location.href // to'liq URL ("https://sayt.uz/mahsulot?id=5#izoh")
location.pathname // "/mahsulot" location.search // "?id=5"
location.hash // "#izoh"
location.href = "/login" // BOSHQA sahifaga o'tish (to'liq qayta yuklash)
location.reload() // sahifani qayta yuklash
history — brauzer tarixi (orqaga/oldinga; SPA routing asosi):
history.back() history.forward()
history.pushState(state, "", "/yangi-url") // URL'ni sahifani qayta yuklamay o'zgartirish
// ❗ React Router aynan shu pushState ustiga qurilgan (11-QISM keyingi boblar)
navigator — brauzer/qurilma haqida: navigator.language ("uz") navigator.onLine (true/false)
screen — ekran: screen.width / height (butun monitor)BOM (Browser Object Model) — DOM sahifaning ichini (hujjat) boshqarsa, BOM brauzer oynasi va muhitini boshqaradigan obyektlar to'plamidir. Markazida
windowturadi — u brauzerdagi global obyekt: har bir global o'zgaruvchi, funksiya, hattodocumentham aslidawindowning xususiyati (window.document),setTimeouthamwindow.setTimeout.location— joriy URL bilan ishlash (href,pathname,search,hash;location.href = "..."bilan boshqa sahifaga o'tish).history— brauzer navigatsiya tarixi; ayniqsahistory.pushStatemuhim: u URL'ni sahifani qayta yuklamay o'zgartiradi — bu SPA (Single Page Application) va React Routerning butun asosidir (11-QISM keyingi boblar shuni ochadi).navigator(til, onlayn holati) vascreen(monitor o'lchami) — muhit haqida ma'lumot. BOM standartlashtirilmagan (brauzerlar biroz farq qiladi), lekinlocation/historyni bilish — routing va autentifikatsiya (redirect) uchun shart.
2.13. localStorage, sessionStorage va sahifa hayot sikli (DOMContentLoaded vs load)
WEB STORAGE — ma'lumotni BRAUZERDA (klientda) saqlash (server emas):
localStorage — DOIMIY (brauzer yopilsa ham qoladi; qo'lda o'chirilguncha)
sessionStorage — VAQTINCHA (faqat shu tab ochiq turganda; tab yopilsa — o'chadi)
localStorage.setItem("kalit", "qiymat"); // yozish
const v = localStorage.getItem("kalit"); // o'qish (yo'q bo'lsa null)
localStorage.removeItem("kalit"); // bittasini o'chirish
localStorage.clear(); // hammasini
❗ FAQAT string saqlaydi → obyekt uchun JSON:
localStorage.setItem("savat", JSON.stringify(savatObyekt)); // yozish
const savat = JSON.parse(localStorage.getItem("savat")) ?? [];// o'qish (null himoyasi)
❗ ~5MB limit; SINXRON (katta ma'lumot UI'ni bloklaydi); parol/token — ehtiyot bo'ling
SAHIFA HAYOT SIKLI (kod QACHON ishlashi):
DOMContentLoaded — HTML tahlil qilinib, DOM TAYYOR (rasm/CSS kutilmaydi) — TEZroq
load — HAMMA resurs (rasm, stil, shrift) yuklandi — kechroq
document.addEventListener("DOMContentLoaded", () => { /* DOM bilan xavfsiz ishlash */ });
❗ <script defer> yoki </body> oxirida bo'lsa — DOM allaqachon tayyor (odatda kifoya)Web Storage — ma'lumotni foydalanuvchi brauzerida (serverga bormay) saqlash mexanizmi.
localStorage— doimiy (brauzer yopilib qayta ochilsa ham qoladi),sessionStorage— vaqtinchalik (faqat joriy tab ochiq turganda). Ikkalasi hamsetItem/getItem/removeItem/clearbilan ishlaydi. Muhim cheklov: faqat matn (string) saqlaydi — obyekt yoki massivni saqlash uchunJSON.stringifybilan yozib,JSON.parsebilan o'qish kerak. Yana: ~5MB limit, sinxron (katta ma'lumot bosh (main) thread'ni bloklaydi), va maxfiy ma'lumot (token, parol) uchun xavfsiz emas (XSS orqali o'g'irlanadi — 14-QISM). Sahifa hayot sikli:DOMContentLoadedhodisasi HTML tahlil qilinib DOM tayyor bo'lganda (rasm/stil kutilmaydi — tezroq) ishga tushadi;loadesa barcha resurslar (rasm, shrift, stil) yuklanganda (kechroq). Odatda skriptnideferbilan yoki</body>oxirida ulasak — DOM allaqachon tayyor bo'ladi (Xato 1). React'da bu bevosita kam uchraydi (ilova bitta root'ga mount qilinadi), lekin storage React'da holatni saqlashda (useEffectichida) juda ko'p ishlatiladi.
2.14. Fetch API — server bilan gaplashish (GET/POST/PUT/DELETE, async/await)
FETCH — brauzerdan serverga HTTP so'rov (5–7 QISM'dagi REST API bilan bog'lanish):
// GET — o'qish (Read):
const res = await fetch("/api/tasks"); // so'rov yuboriladi (Promise qaytaradi)
if (!res.ok) throw new Error(`HTTP ${res.status}`); // ❗ 404/500 ni fetch O'ZI xato demaydi
const data = await res.json(); // javob tanasini JSON'ga aylantirish (yana await)
// POST — yaratish (Create):
const res = await fetch("/api/tasks", {
method: "POST",
headers: { "Content-Type": "application/json" }, // ❗ serverga "men JSON yubordim"
body: JSON.stringify({ title: "Yangi vazifa" }), // ❗ obyekt → string (JSON)
});
// PUT — yangilash (Update): method:"PUT", body: JSON.stringify(o'zgargan)
// DELETE — o'chirish: await fetch(`/api/tasks/${id}`, { method: "DELETE" });
RESPONSE (javob) obyekti:
res.ok // true, agar status 200–299 (muvaffaqiyat)
res.status // 200, 404, 500...
res.json() // tanani JSON obyektga (Promise) res.text() // matn sifatida
❗ fetch faqat TARMOQ uzilsa reject bo'ladi; 404/500 — res.ok=false, xato ATMAYDI → o'zingiz tekshiring
❗ AbortController — so'rovni BEKOR qilish (foydalanuvchi sahifadan chiqib ketsa):
const c = new AbortController();
fetch(url, { signal: c.signal }); c.abort(); // so'rov to'xtatiladiFetch API — brauzerdan serverga HTTP so'rov yuborishning zamonaviy standarti (eski
XMLHttpRequesto'rnini bosgan). U Promise qaytaradi, shuning uchunasync/awaitbilan qulay yoziladi (4-QISM). Bobning sarlavhasidagi "API (CRUD)" aynan shu: DOM CRUD'i sahifani o'zgartirsa, server CRUD'i ma'lumotni REST API orqali saqlaydi —GET(Read),POST(Create),PUT/PATCH(Update),DELETE. POST/PUT'da uchta narsa muhim:method,headers(Content-Type: application/json— serverga "men JSON yubordim" deb aytish), vabody(JSON.stringifybilan obyektni matnga aylantirish). JavobResponseobyekti:res.ok(200–299 bo'lsatrue),res.status,res.json()(tanani obyektga aylantiruvchi yana birPromise— yanaawait). Eng katta tuzoq:fetchfaqat tarmoq uzilganda rad (reject) bo'ladi — 404/500 kabi server xatolaridafetchxato tashlamaydi, faqatres.okfalsebo'ladi; shuning uchun har doimif (!res.ok) throw ...bilan qo'lda tekshirish kerak.AbortController— davom etayotgan so'rovni bekor qiladi (foydalanuvchi sahifani almashtirsa keraksiz so'rovni to'xtatish uchun; React'dauseEffecttozalashida keng ishlatiladi). Bu — 5-QISM (Node/Express API) va 6-QISM (NestJS) da yozgan backend'ingizga frontend'dan ulanishning ko'prigi.
2.15. To'liq CRUD sikli: DOM + REST API birgalikda
HAQIQIY ILOVA = ma'lumot SERVERDA + ko'rinish DOM'da. CRUD ikki tomonda birga yuradi:
┌──────────────┬───────────────────────────┬──────────────────────────────┐
│ AMAL │ SERVER (fetch — REST) │ DOM (ko'rinish — 2.4) │
├──────────────┼───────────────────────────┼──────────────────────────────┤
│ Read (READ) │ GET /api/tasks │ ro'yxatni render qilish │
│ Create │ POST /api/tasks │ yangi <li> qo'shish │
│ Update │ PUT /api/tasks/:id │ <li> matnini/klassini o'zgart │
│ Delete │ DELETE /api/tasks/:id │ <li> ni o'chirish │
└──────────────┴───────────────────────────┴──────────────────────────────┘
ODATIY OQIM (Create):
1. foydalanuvchi forma yuboradi (submit → preventDefault — 2.6)
2. await fetch POST → server yangi yozuvni saqlaydi va {id, ...} qaytaradi
3. server javobidan keyin ma'lumot massivini + DOM'ni yangilash (render)
4. xato bo'lsa (res.ok=false yoki tarmoq) → foydalanuvchiga xabar (catch)
❗ E'TIBOR: bu yerda ENDI IKKI manba sinxron: server ↔ DOM (2.9 muammosi kuchayadi!)
"loading", "xato", "bo'sh" holatlarini ham QO'LDA boshqarish kerak → React shu yerda yutadiTo'liq CRUD sikli — real ilovada ma'lumot serverda (ma'lumotlar bazasi — 7-QISM), ko'rinish esa DOM'da yashaydi, va CRUD ikki tomonda birga bajariladi: har bir amal avval
fetchbilan serverga boradi, so'ng natijaga qarab DOM yangilanadi. Odatiy oqim: forma yuboriladi (preventDefault) →await fetch(POST)→ server saqlab, yangi yozuvni (masalanidbilan) qaytaradi → shundan keyin ma'lumot massivi va DOM yangilanadi → xato bo'lsacatchda foydalanuvchiga xabar beriladi. Bu yerda 2.9'dagi sinxronlash muammosi yanada kuchayadi: endi faqat "massiv ↔ DOM" emas, balki "server ↔ massiv ↔ DOM" uch qatlam mos turishi kerak, ustiga "yuklanmoqda" (loading), "xato" (error), "bo'sh" (empty) holatlarini ham qo'lda boshqarish qo'shiladi. Bularning barchasini vanilla'da qo'lda ushlab turish — juda charchatadi. Aynan shuning uchun React va uning ma'lumot-olish kutubxonalari (masalan keyingi boblardagi yondashuvlar) bu holatlarni tizimli boshqaradi — imperativ DOM'ning og'rig'i bu yerda cho'qqisiga chiqadi.
3. Sintaksis — tez ma'lumotnoma
TANLASH 2.3-bob: document.querySelector(".x") | querySelectorAll("li") | getElementById("id")
NAVIGATSIYA: el.parentElement | el.children | el.closest(".x") | el.nextElementSibling
CREATE 2.4-bob: document.createElement("li") | ul.append(li) | el.prepend/before/after
READ: el.textContent | el.innerHTML (XSS!) | input.value
UPDATE: el.textContent="..." | el.classList.add/remove/toggle("x") | el.style.color
ATRIBUT 2.5-bob: el.setAttribute("href","#") | el.dataset.id | el.getAttribute("href")
DELETE: el.remove() | parent.removeChild(el)
HODISA 2.6-bob: el.addEventListener("click", e => {...}) | e.target | e.preventDefault()
FRAGMENT 2.8-bob: document.createDocumentFragment() | fragment.append(...) | ul.append(fragment)
MASSIVGA: [...nodeList] yoki Array.from(nodeList) // NodeList → Array (map/filter uchun)
QO'SHISH 2.11-bob:el.insertAdjacentHTML("beforeend", html) | el.cloneNode(true) | old.replaceWith(new)
BOM 2.12-bob: location.href | location.pathname | history.pushState(s,"",url) | navigator.language
STORAGE 2.13-bob: localStorage.setItem(k,v) | getItem(k) | JSON.stringify/parse | sessionStorage
HAYOT SIKLI: document.addEventListener("DOMContentLoaded", ...) // DOM tayyor bo'lganda
FETCH 2.14-bob: await fetch(url) | { method, headers, body: JSON.stringify(x) } | res.ok | res.json()4. Batafsil kod namunalari
Misol 1 — Element tanlash va xavfsiz o'qish (2.3)
// Elementni "ushlab olamiz" (avval tanlash — har ishning 1-qadami)
const title = document.querySelector("h1"); // birinchi h1
const items = document.querySelectorAll(".item"); // barcha .item (NodeList)
// ❗ querySelector null qaytarishi mumkin — ishonchli kod tekshiradi
const banner = document.querySelector(".banner");
if (banner) { // topilgan bo'lsa...
banner.textContent = "Xush kelibsiz!"; // ...ishlatamiz
}
// NodeList ustida aylanish (forEach bor; map/filter uchun massivga aylantir)
items.forEach((el, i) => (el.textContent = `Element #${i + 1}`));
const titles = [...items].map(el => el.textContent); // [...] bilan massiv → map ishlaydiMisol 2 — DOM CRUD: yaratish, qo'shish, o'chirish (2.4)
const ul = document.querySelector("#list");
// CREATE — uch qadam: yarat → to'ldir → ula
function addItem(text) {
const li = document.createElement("li"); // 1. yarat (hali sahnada YO'Q)
li.textContent = text; // 2. matnni qo'y (xavfsiz)
li.classList.add("list-item"); // 3. stil klassi
ul.append(li); // 4. daraxtga ula → endi ko'rinadi
return li;
}
const first = addItem("Sut sotib olish");
addItem("Non sotib olish");
// UPDATE — mavjud elementni o'zgartirish
first.textContent = "Sut + qaymoq sotib olish"; // matnni almashtir
first.classList.toggle("done"); // "done" klassini yoq/o'chir
// DELETE — o'zini o'chiradi
first.remove(); // birinchi element o'chdiMisol 3 — innerHTML vs textContent va XSS xavfi (2.4, 14-QISM)
const box = document.querySelector("#box");
const userInput = '<img src=x onerror="alert(\'buzildi!\')">'; // zararli matn (foydalanuvchidan)
// ❌ XAVFLI — innerHTML matnni HTML sifatida bajaradi → XSS hujumi
box.innerHTML = userInput; // <img> yuklanadi, onerror ishlaydi — kod bajarildi!
// ✅ XAVFSIZ — textContent matnni faqat MATN sifatida ko'rsatadi (tegni bajarmaydi)
box.textContent = userInput; // ekranda literal matn ko'rinadi, kod ISHLAMAYDI
// ❗ Qoida: foydalanuvchi kiritgan har qanday narsani textContent bilan chiqaring
// (innerHTML faqat O'ZINGIZ ishonadigan, statik HTML uchun)Misol 4 — classList bilan holatni boshqarish (2.5)
const menu = document.querySelector(".menu");
const burger = document.querySelector(".burger");
// toggle — bor bo'lsa o'chiradi, yo'q bo'lsa qo'shadi (switch tugma uchun ideal)
burger.addEventListener("click", () => {
menu.classList.toggle("open"); // har bosishda ochiq/yopiq
const isOpen = menu.classList.contains("open"); // hozir ochiqmi? (true/false)
burger.setAttribute("aria-expanded", isOpen); // a11y — ekran o'quvchiga xabar (1.9)
});
// ❗ Stilni CSS'da .menu.open { ... } qilib yozamiz — JS faqat klassni almashtiradi
// (mas'uliyat ajratilgan: JS — mantiq, CSS — ko'rinish)Misol 5 — Hodisalar va preventDefault (2.6)
const form = document.querySelector("#login-form");
form.addEventListener("submit", (event) => {
event.preventDefault(); // ❗ sahifa qayta yuklanishini TO'XTAT (forma standarti)
const email = form.querySelector("[name=email]").value; // input qiymati
if (!email.includes("@")) {
alert("Email noto'g'ri");
return; // davom etmaymiz
}
console.log("Yuborilmoqda:", email); // bu yerda fetch/axios bo'lardi (2.18)
});Misol 6 — Event delegation (1 listener, ko'p bola — 2.6)
const list = document.querySelector("#todo-list");
// 100 ta tugmaga 100 ta listener O'RNIGA — otaga 1 ta (xotira/performance)
list.addEventListener("click", (event) => {
// Qaysi bola bosildi? event.target bilan aniqlaymiz
if (event.target.matches(".delete-btn")) { // o'chirish tugmasimi?
event.target.closest("li").remove(); // eng yaqin <li> ni o'chir
}
if (event.target.matches(".toggle-btn")) { // bajarildi tugmasimi?
event.target.closest("li").classList.toggle("done");
}
});
// ❗ Yangi qo'shilgan <li>lar ham AVTOMATIK ishlaydi (listener otada — har doim bor)Misol 7 — DocumentFragment bilan tez ro'yxat qurish (2.8)
const ul = document.querySelector("#big-list");
const data = Array.from({ length: 1000 }, (_, i) => `Mahsulot ${i + 1}`);
// ✅ TEZ — fragmentga to'plab, 1 marta DOM'ga ulash (1 reflow)
const fragment = document.createDocumentFragment(); // ko'rinmas idish (sahnada YO'Q)
for (const text of data) {
const li = document.createElement("li");
li.textContent = text;
fragment.append(li); // fragmentga — REFLOW YO'Q
}
ul.append(fragment); // 1 marta haqiqiy DOM'ga → 1 reflow (2.7)
// ❌ SEKIN bo'lardi: for ichida har safar ul.append(li) → ~1000 reflowMisol 8 — Layout thrashing va uni tuzatish (2.7)
const boxes = document.querySelectorAll(".box");
// ❌ YOMON — o'qish (offsetWidth) va yozishni ARALASHTIRISH → har safar reflow
boxes.forEach(box => {
const w = box.offsetWidth; // O'QISH → brauzer reflow'ni majburlaydi
box.style.width = w + 10 + "px"; // YOZISH → keyingi o'qish yana reflow...
});
// ✅ YAXSHI — avval HAMMASINI o'qi, KEYIN hammasini yoz (reflow'lar ajratilgan)
const widths = [...boxes].map(box => box.offsetWidth); // 1-faza: faqat o'qish
boxes.forEach((box, i) => (box.style.width = widths[i] + 10 + "px")); // 2-faza: faqat yozishMisol 9 — To'liq imperativ "Vazifalar" ilovasi (2.9 og'rig'ini his qil)
// === Ma'lumot (state) — DOM'dan ALOHIDA yashaydi ===
let tasks = [];
const input = document.querySelector("#task-input");
const ul = document.querySelector("#task-list");
const counter = document.querySelector("#counter");
const empty = document.querySelector("#empty-msg");
// === HAR o'zgarishda QO'LDA chaqiriladigan "qayta chizish" funksiyasi ===
function render() {
ul.innerHTML = ""; // eski ro'yxatni tozalash (yana qurish uchun)
const fragment = document.createDocumentFragment();
tasks.forEach((task, i) => {
const li = document.createElement("li");
li.textContent = task.title;
if (task.done) li.classList.add("done");
const del = document.createElement("button");
del.textContent = "🗑";
del.dataset.index = i; // qaysi vazifa? (DOM↔ma'lumot bog'lash — 2.5)
li.append(del);
fragment.append(li);
});
ul.append(fragment);
counter.textContent = `Jami: ${tasks.length}`; // ✏️ hisoblagichni QO'LDA yangila
empty.style.display = tasks.length ? "none" : "block"; // ✏️ "Bo'sh" xabarini QO'LDA boshqar
}
input.addEventListener("keydown", (e) => {
if (e.key === "Enter" && input.value.trim()) {
tasks.push({ title: input.value.trim(), done: false });
input.value = "";
render(); // ❗ o'zgardi → QO'LDA render chaqirish
}
});
ul.addEventListener("click", (e) => { // delegation (2.6)
if (e.target.matches("button")) {
tasks.splice(e.target.dataset.index, 1); // ma'lumotdan o'chir
render(); // ❗ yana QO'LDA render
}
});
// ❗ DIQQAT: har o'zgarishda render() ni QO'LDA chaqiryapmiz. Unutsak — UI eskirib qoladi.
// React'da bu render AVTOMATIK (state o'zgarsa — UI o'zi yangilanadi). Mana farq!Misol 10 — Xuddi shu ilova React'da qanday ko'rinishini oldindan ko'rish (ko'prik)
// === Bu — KEYINGI boblardagi React (hozir tushunish shart emas, FARQNI ko'r) ===
function TaskApp() {
const [tasks, setTasks] = useState([]); // ma'lumot React'da yashaydi
const add = (title) => setTasks([...tasks, { title, done: false }]); // faqat ma'lumotni o'zgartir
const remove = (i) => setTasks(tasks.filter((_, idx) => idx !== i));
// ❗ "render()" YO'Q — UI ma'lumotning funksiyasi (UI = f(state)). React o'zi yangilaydi:
return (
<div>
<input onKeyDown={(e) => e.key === "Enter" && add(e.target.value)} />
<ul>
{tasks.map((task, i) => (
<li key={i} className={task.done ? "done" : ""}>
{task.title}
<button onClick={() => remove(i)}>🗑</button>
</li>
))}
</ul>
<p>Jami: {tasks.length}</p> {/* avtomatik yangilanadi */}
{tasks.length === 0 && <p>Bo'sh</p>} {/* shart — avtomatik */}
</div>
);
}
// ❗ Misol 9 da render() ni 2 marta QO'LDA chaqirdik + hisoblagich/xabarni qo'lda yangiladik.
// Bu yerda — faqat tasks ni o'zgartiramiz, qolganini React qiladi. Mana shu — declarative.Misol 11 — insertAdjacentHTML, cloneNode va replaceWith (2.11)
const ul = document.querySelector("#list");
// insertAdjacentHTML — mavjud ro'yxatni qayta qurmay, faqat yangi elementni qo'shish
// (innerHTML += dan afzal: eski <li>lardagi listenerlar saqlanadi, reflow kamroq)
const xavfsizNom = "Sut"; // ishonchli/ekranlangan matn bo'lishi shart
ul.insertAdjacentHTML("beforeend", `<li>${xavfsizNom}</li>`);
// cloneNode — <template> ichidagi shablonni takrorlash (tez usul)
const tpl = document.querySelector("#row-template"); // <template id="row-template"><li>...</li></template>
const nusxa = tpl.content.firstElementChild.cloneNode(true); // true = bolalari bilan chuqur nusxa
nusxa.querySelector(".name").textContent = "Non"; // nusxani to'ldiramiz
ul.append(nusxa);
// replaceWith — bir elementni boshqasi bilan almashtirish (eski replaceChild o'rniga)
const eski = ul.querySelector("li");
const yangi = document.createElement("li");
yangi.textContent = "Almashtirildi";
eski.replaceWith(yangi); // eski o'rnida endi yangi turadiMisol 12 — localStorage bilan holatni saqlash (2.13)
const SAVAT_KALIT = "savat";
// O'qish — brauzerda saqlangan savatni tiklash (yo'q bo'lsa bo'sh massiv)
function savatniYukla() {
const xom = localStorage.getItem(SAVAT_KALIT); // string yoki null
return xom ? JSON.parse(xom) : []; // ❗ null himoyasi + JSON.parse
}
// Yozish — obyekt/massivni saqlashdan oldin string'ga aylantirish shart
function savatniSaqla(savat) {
localStorage.setItem(SAVAT_KALIT, JSON.stringify(savat)); // ❗ obyekt → JSON string
}
let savat = savatniYukla(); // sahifa ochilganda tiklaymiz
savat.push({ nom: "Sut", narx: 12000 });
savatniSaqla(savat); // har o'zgarishda saqlaymiz
// ❗ localStorage FAQAT string saqlaydi; token/parol saqlash xavfli (XSS — 14-QISM)Misol 13 — Fetch bilan REST API: GET va POST, xato boshqaruvi (2.14)
const API = "/api/tasks";
// READ (GET) — ro'yxatni serverdan olish
async function tasksniOl() {
const res = await fetch(API);
if (!res.ok) throw new Error(`HTTP ${res.status}`); // ❗ 404/500 ni O'ZIMIZ tekshiramiz
return res.json(); // javob tanasi → obyekt (Promise)
}
// CREATE (POST) — yangi vazifa yaratish
async function taskQosh(title) {
const res = await fetch(API, {
method: "POST",
headers: { "Content-Type": "application/json" }, // ❗ "men JSON yubordim"
body: JSON.stringify({ title, done: false }), // ❗ obyekt → JSON string
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json(); // server qaytargan yangi yozuv (id bilan)
}
// Ishlatish — xato boshqaruvi bilan (foydalanuvchiga bildirish)
(async () => {
try {
const yangi = await taskQosh("Kitob o'qish"); // serverga yozamiz
const barchasi = await tasksniOl(); // yangilangan ro'yxatni olamiz
console.log("Yaratildi:", yangi, "Jami:", barchasi.length);
} catch (err) {
console.error("So'rov muvaffaqiyatsiz:", err.message); // tarmoq yoki server xatosi
}
})();Misol 14 — To'liq CRUD: DOM + REST API + AbortController (2.14, 2.15)
const API = "/api/tasks";
const ul = document.querySelector("#task-list");
const status = document.querySelector("#status"); // "yuklanmoqda / xato" xabari uchun
let tasks = []; // lokal nusxa (server ↔ DOM oralig'ida)
// Markazlashgan render — server ↔ DOM sinxronini bitta joyda ushlash (2.9, 2.15)
function render() {
ul.innerHTML = "";
const fragment = document.createDocumentFragment();
tasks.forEach((t) => {
const li = document.createElement("li");
li.textContent = t.title; // XSS'siz (textContent — 2.4)
if (t.done) li.classList.add("done");
const del = document.createElement("button");
del.textContent = "🗑";
del.dataset.id = t.id; // qaysi yozuv? (DOM↔ma'lumot — 2.5)
li.append(del);
fragment.append(li);
});
ul.append(fragment); // 1 marta DOM'ga (2.8)
}
// READ — ilova boshida ro'yxatni yuklash (loading/error holatlari bilan)
async function yukla() {
status.textContent = "Yuklanmoqda..."; // ✏️ loading holatini QO'LDA
try {
const res = await fetch(API);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
tasks = await res.json();
status.textContent = tasks.length ? "" : "Ro'yxat bo'sh"; // ✏️ empty holatini QO'LDA
render(); // ✏️ DOM'ni QO'LDA yangilash
} catch (err) {
status.textContent = "Xato: " + err.message; // ✏️ error holatini QO'LDA
}
}
// DELETE — server + DOM (delegation orqali, 2.6)
ul.addEventListener("click", async (e) => {
if (!e.target.matches("button")) return;
const id = e.target.dataset.id;
try {
const res = await fetch(`${API}/${id}`, { method: "DELETE" });
if (!res.ok) throw new Error(`HTTP ${res.status}`);
tasks = tasks.filter((t) => String(t.id) !== id); // ✏️ massivdan o'chirish
render(); // ✏️ DOM'ni yangilash
} catch (err) {
status.textContent = "O'chirishda xato: " + err.message;
}
});
// AbortController — sahifadan chiqilsa davom etayotgan so'rovni bekor qilish
const controller = new AbortController();
fetch(API, { signal: controller.signal });
window.addEventListener("beforeunload", () => controller.abort()); // keraksiz so'rovni to'xtat
yukla();
// ❗ DIQQAT: loading/error/empty + server↔massiv↔DOM sinxronini HAMMASINI qo'lda ushladik.
// React va uning ma'lumot-olish yondashuvlari aynan shu holatlarni tizimli boshqaradi 2.15-bob.5. To'g'ri va noto'g'ri holatlar
1) Foydalanuvchi kiritgan matnni chiqarish
❌ box.innerHTML = userInput (XSS xavfi — kod bajariladi — Misol 3)
✅ box.textContent = userInput (faqat matn sifatida — xavfsiz)2) Ko'p element qo'shish
❌ for ichida ul.append(li) 1000 marta (1000 reflow — sekin)
✅ DocumentFragment'ga to'plab 1 marta append (1 reflow — Misol 7)3) Ko'p bolaga hodisa
❌ har <li> ga alohida addEventListener (xotira, yangi li ishlamaydi)
✅ otaga 1 ta listener + event delegation (Misol 6)4) querySelector natijasi
❌ document.querySelector(".x").textContent (element yo'q bo'lsa — crash)
✅ const el = querySelector(".x"); if (el) el.textContent = ... (Misol 1)5) Stilni boshqarish
❌ el.style.color = "red" (ko'rinish JS'ga aralashib ketadi)
✅ el.classList.toggle("active") + CSS'da .active{} (mas'uliyat ajratilgan — Misol 4)6) O'qish/yozishni aralashtirish
❌ tsiklda offsetWidth o'qib, darrov style yozish (layout thrashing — Misol 8)
✅ avval hamma o'qish, keyin hamma yozish (ikki fazaga ajrat)7) Fetch javobini tekshirish
❌ const data = await (await fetch(url)).json() (404/500 sezilmaydi — buzuq ma'lumot)
✅ if (!res.ok) throw new Error(res.status); keyin res.json() (Misol 13)8) Obyektni localStorage'ga saqlash
❌ localStorage.setItem("savat", savatObyekt) ("[object Object]" saqlanadi — buziladi)
✅ localStorage.setItem("savat", JSON.stringify(savatObyekt)) (Misol 12)6. Keng tarqalgan xatolar va yechimlari
Xato 1 — Uncaught TypeError: Cannot read properties of null (reading 'textContent')
Sababi: querySelector element topmadi (null), unga .textContent qildik. Ko'pincha skript HTML'dan oldin ishga tushgan (element hali yo'q), yoki selektor xato. Yechimi: skriptni </body> oxirida yoki defer bilan ulang; selektorni tekshiring; natijani if (el) bilan tekshiring (Misol 1).
Xato 2 — Yangi qo'shilgan elementga hodisa ishlamaydi
Sababi: addEventListenerni faqat mavjud elementlarga qo'ygansiz; keyin qo'shilganlarda listener yo'q. Yechimi: event delegation — otaga listener qo'ying, e.target bilan ajrating (2.6, Misol 6).
Xato 3 — el.style.background-color ishlamaydi
Sababi: style xususiyatlari camelCase bo'lishi kerak. Yechimi: el.style.backgroundColor = "..." (yoki el.style.setProperty("background-color", "...")).
Xato 4 — Sahifa forma yuborilgach qayta yuklanib ketadi
Sababi: forma submit'ida event.preventDefault() chaqirilmagan (brauzer standarti — sahifani qayta yuklash). Yechimi: form.addEventListener("submit", e => { e.preventDefault(); ... }) (Misol 5).
Xato 5 — querySelectorAll(...).map is not a function
Sababi: querySelectorAll NodeList qaytaradi — massiv emas, map yo'q. Yechimi: [...nodeList].map(...) yoki Array.from(nodeList).map(...) 2.3-bob.
Xato 6 — Sahifa ko'p element bilan qotib qoladi (sekin)
Sababi: tsiklda DOM'ga ko'p marta tegish (har safar reflow — 2.7). Yechimi: DocumentFragment yoki string to'plab bir marta qo'llash (Misol 7); o'qish/yozishni ajratish (Misol 8).
Xato 7 — UI ma'lumotga mos kelmaydi (ekranda 3 ta, ma'lumotda 2 ta)
Sababi: ma'lumotni o'zgartirib, DOM'ni (yoki uning bir qismini) yangilashni unutgansiz (2.9 — sinxronlash muammosi). Yechimi: vanilla'da — markazlashgan render() funksiyasi (Misol 9); to'g'ri yechim — React (Misol 10).
Xato 8 — fetch 404/500 da ham "ishladi" deb hisoblanadi (buzuq ma'lumot)
Sababi: fetch faqat tarmoq uzilganda rad bo'ladi; server 404/500 qaytarsa Promise baribir bajariladi va .json() xato tanani o'qiydi. Yechimi: har doim if (!res.ok) throw new Error(res.status) bilan qo'lda tekshirish, so'ng res.json() (2.14, Misol 13).
Xato 9 — localStorageda obyekt "[object Object]" bo'lib buzilib qoladi
Sababi: localStorage faqat matn saqlaydi; obyektni to'g'ridan berganda u avtomatik String() bilan "[object Object]"ga aylanadi. Yechimi: yozishda JSON.stringify, o'qishda JSON.parse (null himoyasi bilan — 2.13, Misol 12).
7. Integratsiya — bu mavzu stack'ning qayerida uchraydi
- JS DOM 2.16-bob: bu bob uning frontend rakursidagi chuqur takrori.
- Brauzer rendering 0.5-bob: critical rendering path shu yerda amalda.
- HTML/CSS (1-QISM): DOM — HTML'ning jonli ko'rinishi; classList — CSS bilan ko'prik.
- Node/Express API (5-QISM), NestJS (6-QISM):
fetchshu backend'ga frontend'dan ulanadi (REST CRUD — 2.14, 2.15). - Ma'lumotlar bazasi (7-QISM): server CRUD'i oxir-oqibat DB'ga yozadi; DOM — uning ko'rinishi.
- Async/await, Promise (4-QISM):
fetchvares.json()— Promise; xato boshqaruvitry/catch. - React (11.2+): Virtual DOM — bu bobdagi fragment/reflow muammolarini avtomatlashtiradi; ma'lumot-olish (
useEffect+ fetch) — 2.14/2.15 ning React versiyasi. - Routing:
history.pushState2.12-bob — SPA va React Router asosi. - Performance 11.11-bob: reflow/repaint — React optimizatsiyasining asosi.
- Forma 11.10-bob:
value,submit,preventDefault— React'da controlled input asosi. - Xavfsizlik (14-QISM): innerHTML/XSS (2.4, 2.11), localStorage'da token saqlash xavfi 2.13-bob — React
dangerouslySetInnerHTMLbilan bog'liq.
8. Eng yaxshi amaliyotlar (best practices)
textContentstandart,innerHTMLehtiyotkorlik (foydalanuvchi matnini hech qachon innerHTML'ga — XSS — Misol 3).querySelectornatijasini tekshirish (nullbo'lishi mumkin — Misol 1).- Stilni
classListbilan (ko'rinish CSS'da; JS faqat klass almashtiradi — Misol 4). - Event delegation (ko'p bolaga 1 listener — xotira, dinamik elementlar — Misol 6).
- DOM'ga teginishni minimallashtirish (fragment, string to'plab; tsiklda append qilmaslik — Misol 7).
- O'qish/yozishni ajratish (layout thrashing'dan qochish — Misol 8).
- Skriptni
deferbilan yoki body oxirida (DOM tayyor bo'lgach ishlasin — Xato 1). fetchjavobini har doimres.okbilan tekshirish (404/500 xato tashlamaydi — Misol 13).fetchnitry/catchga o'rash va loading/error/empty holatlarni ko'rsatish (Misol 14).localStoragega obyektniJSON.stringifybilan yozish (faqat string saqlaydi — Misol 12); token/parol saqlamaslik (XSS — 14-QISM).insertAdjacentHTMLniinnerHTML +=o'rniga (konteynerni qayta qurmaydi, listenerlar saqlanadi — 2.11).- Ma'lumotni yagona manba qilish (UI — ma'lumotning aksi; markazlashgan render — bu fikr React'ga olib boradi — 2.9, 2.10).
9. Amaliy loyiha: "Vanilla DOM bilan Savatcha (imperativ)"
Bu loyiha — ataylab vanilla JS'da (React'siz). Maqsad — imperativ DOM'ning og'rig'ini o'z qo'lingiz bilan his qilish, toki keyingi bobda React sizni "ozod qilganda" uning qadrini bilasiz.
Maqsad
Faqat HTML + CSS + vanilla JS bilan ishlaydigan onlayn do'kon savatchasi yarating: mahsulot qo'shish, sonini o'zgartirish, o'chirish, umumiy narxni hisoblash.
Talablar (requirements)
- Mahsulotlar ro'yxati: kamida 5 ta mahsulot (nom, narx, rasm/emoji) — massivdan DOM'ga chiqarish (Misol 7 — fragment).
- Savatga qo'shish: "Qo'shish" tugmasi mahsulotni savatga qo'shsin (delegation — Misol 6).
- Son boshqaruvi: savatda har mahsulot uchun
+/−tugmalari (son 0 bo'lsa — o'chirilsin). - O'chirish: savatdan mahsulotni butunlay o'chirish ().
- Umumiy narx: har o'zgarishda "Jami: X so'm" avtomatik yangilansin.
- Bo'sh holat: savat bo'sh bo'lsa "Savat bo'sh" xabari ko'rsatilsin.
- Markazlashgan render: barcha o'zgarishlar bitta
renderCart()funksiyasidan o'tsin (Misol 9 uslubi). - XSS himoyasi: mahsulot nomini
textContentbilan chiqarish (Misol 3). - Performance: ro'yxatni fragment bilan qurish; tsiklda to'g'ridan append qilmaslik (Misol 7).
- a11y: tugmalarga
aria-label; klaviatura bilan ham ishlasin 1.9-bob. - Doimiylik: savat
localStorageda saqlansin (JSON.stringify/parse), sahifa qayta yuklanganda tiklansin (2.13, Misol 12). - (ixtiyoriy) API: agar backend bo'lsa, savatni
fetchbilan serverga yozib/o'qib ko'ring;res.okvatry/catchbilan xatoni boshqaring (2.14, Misol 13–14).
Maslahatlar (hint)
- Ma'lumotni (savat) bitta massivda saqlang; DOM — uning aksi (har o'zgarishda
renderCart()). - Har bir o'zgarishdan keyin
renderCart()ni qo'lda chaqirishni unutmang — va aynan shu "unutmaslik kerakligi" React'ning sababi 2.9-bob. dataset.idbilan DOM tugmasini ma'lumotga bog'lang (qaysi mahsulot bosildi).- Son va narxni har safar massivdan qayta hisoblang (DOM'dan o'qimang — ma'lumot — yagona manba).
- Sanang: ilova oxirida
renderCart()ni necha marta qo'lda chaqirdingiz? Har biri — React qiladigan ish.
"Tayyor" mezonlari (acceptance criteria)
- Mahsulotlar massivdan DOM'ga chiqadi (fragment bilan).
- Savatga qo'shish/o'chirish ishlaydi (delegation bilan).
-
+/−son boshqaruvi (0 da o'chadi). - Umumiy narx har o'zgarishda to'g'ri yangilanadi.
- Savat bo'sh bo'lsa "Bo'sh" xabari chiqadi.
- Barcha o'zgarish markazlashgan
renderCart()dan o'tadi. - Mahsulot nomi
textContentbilan (XSS yo'q). - Tsiklda to'g'ridan-to'g'ri append yo'q (fragment ishlatilgan).
- UI hech qachon ma'lumotga zid kelmaydi (sinxron).
- Savat
localStorageda saqlanadi va sahifa qayta yuklanganda tiklanadi.
Bu loyiha — mustaqil amaliyot uchun. Yuqoridagi talab va maslahatlardan foydalanib, savatchani o'zingiz to'liq yozib ko'ring; Misol 9 dagi markazlashgan
render()uslubi asosiy suyanchiq bo'ladi.
10. Xulosa va keyingi bobga ko'prik
Bu bobda frontend'ning poydevori — brauzer va DOM — ni chuqur takrorladik:
- Critical Rendering Path (HTML→DOM, CSS→CSSOM, render tree, layout, paint — 2.1); DOM daraxti va node turlari 2.2-bob.
- Tanlash (querySelector — 2.3); CRUD (create/read/update/delete — 2.4); class/style/dataset 2.5-bob; hodisalar (delegation, bubbling — 2.6).
- Reflow/repaint (nega qo'lda DOM sekin — 2.7); DocumentFragment (batching — 2.8).
- Va eng muhimi — imperativ DOM'ning tub muammosi (state ↔ UI ni qo'lda sinxronlash — 2.9) va undan chiqish yo'li: deklarativ yondashuv,
UI = f(state)2.10-bob. - Qo'shimcha manipulyatsiya (
insertAdjacentHTML,cloneNode,replaceWith— 2.11); BOM (window,location,history,navigator— 2.12); Web Storage va sahifa hayot sikli (localStorage,DOMContentLoaded— 2.13). - Fetch API (GET/POST/PUT/DELETE,
res.ok,async/await,AbortController— 2.14) va to'liq CRUD sikli (DOM + REST API birga; loading/error/empty holatlar — 2.15) — bobning "API (CRUD)" qismi.
Endi siz vanilla DOM bilan har narsani qila olasiz — lekin har o'zgarishda render() ni qo'lda chaqirish, qaysi joyni yangilashni eslab qolish, sinxronlashni qo'lda ushlab turishning og'rig'ini his qildingiz. Bu og'riq tasodifiy emas — u butun bir kutubxonaning tug'ilish sababi.
Keyingi bob — 11.2-bob: React kirish — JSX, komponentlar, props. Endi avtomat qo'g'irchoqchini ishga solamiz. React'ning markaziy g'oyasi — UI'ni mustaqil, qayta ishlatiladigan bo'laklar (komponentlar)ga bo'lish va ularni JSX (JavaScript ichida HTML'ga o'xshash sintaksis) bilan deklarativ tasvirlash. Siz render() ni qo'lda chaqirishni unutasiz — chunki React buni state o'zgarganda avtomatik qiladi. "Qanday" emas, "nima" deb fikrlashni boshlaymiz.
Foydalanilgan rasmiy/ishonchli manbalar
- MDN Web Docs — Document Object Model (DOM),
Document.querySelector,Node,Element,DocumentFragment - MDN Web Docs — "Introduction to events", Event delegation,
EventTarget.addEventListener - MDN Web Docs — Fetch API,
Response,Request,AbortController; Web Storage API (localStorage,sessionStorage) - MDN Web Docs — Browser Object Model:
Window,Location,History,Navigator - web.dev (Google) — "Critical Rendering Path", "Avoid large, complex layouts and layout thrashing"
- HTML Living Standard (WHATWG) — DOM, events,
history.pushState, scriptdefer - React rasmiy hujjati (react.dev) — "Thinking in React", "Reacting to Input with State" (deklarativ falsafa)
O'qiganingizni mustahkamlang
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!