
> Скица от [Tomomi Imura](https://twitter.com/girlie_mac)
Типовете данни са една от основните концепции в JavaScript, с които ще се сблъскате във всяка програма, която пишете. Представете си типовете данни като система за класификация, използвана от древните библиотекари в Александрия – те са имали специални места за свитъци с поезия, математика и исторически записи. JavaScript организира информацията по подобен начин, като използва различни категории за различни видове данни.
В този урок ще разгледаме основните типове данни, които правят JavaScript функционален. Ще научите как да работите с числа, текст, стойности истина/лъжа и защо е важно да избирате правилния тип за вашите програми. Тези концепции може да изглеждат абстрактни в началото, но с практика ще станат естествени.
Разбирането на типовете данни ще направи всичко останало в JavaScript много по-ясно. Точно както архитектите трябва да разбират различните строителни материали, преди да построят катедрала, тези основи ще подкрепят всичко, което изграждате занапред.
## Тест преди лекцията
[Тест преди лекцията](https://ff-quizzes.netlify.app/web/)
Този урок обхваща основите на JavaScript, езикът, който осигурява интерактивност в уеб пространството.
> Можете да преминете този урок на [Microsoft Learn](https://docs.microsoft.com/learn/modules/web-development-101-variables/?WT.mc_id=academic-77807-sagibbon)!
[](https://youtube.com/watch?v=JNIXfGiDWM8 "Променливи в JavaScript")
[](https://youtube.com/watch?v=AWfA95eLdq8 "Типове данни в JavaScript")
> 🎥 Кликнете върху изображенията по-горе за видеа относно променливи и типове данни
Нека започнем с променливите и типовете данни, които ги запълват!

> Скетчноут от [Tomomi Imura](https://twitter.com/girlie_mac)
```mermaid
journey
title Вашето приключение с типовете данни в JavaScript
section Основа
Променливи и Константи: 5: You
Синтаксис на обявяване: 4: You
Концепции за присвояване: 5: You
section Основни типове
Числа и Математика: 4: You
Низове и Текст: 5: You
Булеви стойности и Логика: 4: You
section Приложете знанията
Преобразуване на типове: 4: You
Примери от реалния свят: 5: You
Добри практики: 5: You
```
Типовете данни са една от фундаменталните концепции в JavaScript, с които ще се срещнете във всеки писан от вас програмен код. Представете си типовете данни като система за подреждане, използвана от древните библиотекари в Александрия – те имаха определени места за свитъци с поезия, математика и исторически записи. JavaScript организира информацията по подобен начин с различни категории за различни видове данни.
В този урок ще разгледаме основните типове данни, които карат JavaScript да работи. Ще научите как да работите с числа, текст, булеви стойности истинно/невярно и да разберете защо изборът на правилния тип е съществен за вашите програми. Тези концепции може да изглеждат абстрактни в началото, но с практиката ще станат втора природа.
Разбирането на типовете данни ще направи всичко останало в JavaScript много по-ясно. Точно както архитектите трябва да познават различните строителни материали преди да издигнат катедрала, основните понятия тук ще подкрепят всичко, което изграждате занапред.
Този урок обхваща основите на JavaScript, езикът, който осигурява интерактивност в уеб.
> Можете да вземете този урок в [Microsoft Learn](https://docs.microsoft.com/learn/modules/web-development-101-variables/?WT.mc_id=academic-77807-sagibbon)!
[](https://youtube.com/watch?v=JNIXfGiDWM8 "Variables in JavaScript")
[](https://youtube.com/watch?v=AWfA95eLdq8 "Data Types in JavaScript")
> 🎥 Кликнете на изображенията по-горе за видеа за променливи и типове данни
Нека започнем с променливите и типове данни, които ги пълнят!
```mermaid
mindmap
root((Данни в JavaScript))
Variables
let myVar
const PI = 3.14
var oldStyle
Primitive Types
number
42
3.14
-5
string
"Здравей"
'Свят'
`Шаблон`
boolean
true
false
undefined
null
Operations
Arithmetic
+ - * / %
String Methods
конкатенация
шаблонни литерали
Type Conversion
имплицитно
експлицитно
```
## Променливи
Променливите са основни градивни елементи в програмирането. Както етикетираните буркани, които средновековните алхимици са използвали за съхранение на различни вещества, променливите ви позволяват да съхранявате информация и да ѝ дадете описателно име, за да можете да я използвате по-късно. Трябва да запомните нечия възраст? Съхранете я в променлива, наречена `age`. Искате да следите името на потребител? Запазете го в променлива, наречена `userName`.
Променливите са основни градивни блокове в програмирането. Като надписаните буркани, които средновековните алхимици използваха за съхранение на различни субстанции, променливите ви позволяват да съхранявате информация и да ѝ дадете описателно име, за да може да я позовавате по-късно. Трябва ли да запомните нечия възраст? Съхранете я в променлива на име `age`. Искате ли да следите името на потребител? Запазете го в променливас име`userName`.
Ще се фокусираме върху съвременния подход за създаване на променливи в JavaScript. Техниките, които ще научите тук, представляват години на еволюция на езика и най-добрите практики, разработени от програмистката общност.
Ще се фокусираме върху съвременния подход за създаване на променливи в JavaScript. Техниките, които ще научите тук, представляват години еволюция на езика и най-добри практики, разработени от програмистката общност.
Създаването и **декларирането** на променлива има следния синтаксис **[ключова дума] [име]**. Състои се от две части:
Създаването и **декларирането** на променлива има следния синтаксис **[ключова дума] [име]**. Тосе състои от две части:
- **Ключова дума**. Използвайте `let` за променливи, които могат да се променят, или `const` за стойности, които остават същите.
- **Името на променливата**, това е описателно име, което сами избирате.
- **Ключова дума**. Използвайте `let` за променливи, които могат да се променят, или `const` за стойности, които остават постоянни.
- **Името на променливата**, това е описателно име, което избирате сами.
✅ Ключовата дума `let` беше въведена в ES6 и дава на вашата променлива така наречената _блокова област на видимост_. Препоръчително е да използвате `let` или `const` вместо по-старото `var`. Ще разгледаме блоковите области на видимост по-подробно в бъдещи части.
✅ Ключовата дума `let` беше въведена в ES6 и дава на вашата променлива така наречената _блоковаобхватност_. Препоръчително е да използвате `let` или `const` вместо по-старата ключова дума `var`. Ще разгледаме блоковите обхвати по-подробно в бъдещи части.
### Задача - работа с променливи
1. **Декларирайте променлива**. Нека започнем, като създадем първата си променлива:
1. **Декларирайте променлива**. Нека започнемс създаването на първата ни променлива:
```javascript
let myVariable;
```
**Какво постигаме с това:**
- Това казва на JavaScript да създаде място за съхранение, наречено `myVariable`
- JavaScript отделя място в паметта за тази променлива
**Какво сепостига с това:**
- Казва на JavaScript да създаде място за съхранение с име`myVariable`
- JavaScript заделя пространство в паметта за тази променлива
- Променливата в момента няма стойност (undefined)
2. **Дайте ѝ стойност**. Сега нека поставим нещо в нашата променлива:
2. **Дайте ѝ стойност**. Сега нека сложим нещо в нашата променлива:
```javascript
myVariable = 123;
```
**Как работи присвояването:**
- Операторът `=` присвоява стойността 123 на нашата променлива
- Променливата вече съдържа тази стойност вместо да бъде undefined
- Можете да използвате тази стойност в целия си код, като използвате `myVariable`
**Как работи задаването:**
- Операторът `=` приравнява стойността 123 към нашата променлива
- Първоначалната undefined стойност се заменя с тази числова стойност
- Можете да използвате тази стойност в кода си чрез `myVariable`
> Забележка: използването на `=` в този урок означава, че използваме "оператор за присвояване", който служи за задаване на стойност на променлива. Това не означава равенство.
> Забележка: използването на `=` в този урок означава, че ползваме "оператор за присвояване", който задава стойност на променлива. Не означава равенство.
3. **Направете го по-умно**. Всъщност, нека комбинираме тези две стъпки:
3. **Правете го по умен начин**. Всъщност, нека комбинираме тези две стъпки:
```javascript
let myVariable = 123;
```
**Този подход е по-ефективен:**
- Декларирате променливата и присвоявате стойност в едно изречение
- Декларирате променливата и ѝ задавате стойност в едно изречение
- Това е стандартна практика сред разработчиците
- Намалява дължината на кода, като същевременно запазва яснотата
- Намалява дължината на кода, като същевременно запазва яснота
4. **Променете мнението си**. Ами ако искаме да съхраним различно число?
4. **Променете решението си**. Ами ако искаме да съхраним друго число?
```javascript
myVariable = 321;
```
**Разбиране на повторно присвояване:**
**Разбиране на повторното задаване:**
- Променливата вече съдържа 321 вместо 123
- Предишната стойност е заменена – променливите съхраняват само една стойност наведнъж
- Предишната стойност се заменя – променливите съхраняват само една стойност в даден момент
- Тази изменяемост е ключова характеристика на променливите, декларирани с`let`
✅ Опитайте! Можете да пишете JavaScript директно в браузъра си. Отворете прозорец на браузъра и отидете в Developer Tools. В конзолата ще намерите поле за въвеждане; напишете `let myVariable = 123`, натиснете Enter, след това напишете `myVariable`. Какво се случва? Забележете, че ще научите повече за тези концепции в следващите уроци.
✅ Опитайте сами! Можете да пишете JavaScript директно в браузъра си. Отворете прозорец на браузъра и отидете в Инструментите за разработчици. В конзолата ще намерите ред за въвеждане; напишете `let myVariable = 123`, натиснете Enter, след това напишете `myVariable`. Какво се случва? Ще научите повече за тези понятия в следващите уроци.
### 🧠 **Проверка на овладяване на променливите: Да свикнем с тях**
**Нека видим как се справяте с променливите:**
- Можете ли да обясните разликата между деклариране и задаване на променлива?
- Какво се случва, ако опитате да използвате променлива преди да я декларирате?
- Кога бихте избрали `let` пред `const` за променлива?
```mermaid
stateDiagram-v2
[*] --> Declared: нека myVar
Declared --> Assigned: myVar = 123
Assigned --> Reassigned: myVar = 456
Assigned --> [*]: Променливата е готова!
Reassigned --> [*]: Актуализирана стойност
note right of Declared
Променливата съществува, но
няма стойност (неопределена)
end note
note right of Assigned
Променливата съдържа
стойност 123
end note
```
> **Бърз съвет**: Помислете за променливите като за надписани кутии за съхранение. Създавате кутията (`let`), слагате нещо в нея (`=`) и може по-късно да смените съдържанието ѝ ако е необходимо!
## Константи
Понякога трябва да съхранявате информация, която никога не трябва да се променя по време на изпълнението на програмата. Представете си константите като математическите принципи, които Евклид е установил в древна Гърция – веднъж доказани и документирани, те остават непроменени за бъдещи справки.
Понякога е нужно да съхранявате информация, която никога не трябва да се променя по време на изпълнението на програмата. Помислете за константите като за математическите принципи, които Евклид установил в древна Гърция – веднъж доказани и документирани, те останали неизменни за всички следващи препратки.
Константите работят подобно на променливите, но с важно ограничение: веднъж зададена стойност, тя не може да бъде променена. Тази неизменност помага да се предотвратят случайни модификации на критични стойности в програмата ви.
Константите работят подобно на променливите, но с важно ограничение: след като им зададете стойност, тя не може да бъде променяна. Тази неизменяемост помага да се предотвратят случайни промени на критични стойности в програмата ви.
Декларирането и инициализацията на константа следва същите концепции като променлива, с изключение на ключовата дума `const`. Константите обикновено се декларират с главни букви.
Декларирането и инициализацията на константа следва същите концепции като при променлива, с изключение на ключовата дума `const`. Обикновено константитесе декларират с главни букви.
```javascript
const MY_VARIABLE = 123;
```
**Какво прави този код:**
- **Създава** константа, наречена `MY_VARIABLE` със стойност 123
- **Използва** конвенция за именуване с главни букви за константи
- **Предотвратява** всякакви бъдещи промени на тази стойност
**Ето какво прави този код:**
- **Създава** константа на име`MY_VARIABLE` със стойност 123
- **Използва** конвенцията за име с главни букви при константи
- **Предотвратява** бъдещи промени на тази стойност
Константите имат две основни правила:
Константите имат два основни правила:
- **Трябва да им дадете стойност веднага** – не се допускат празни константи!
- **Никога не можете да променяте тази стойност** – JavaScript ще изведе грешка, ако опитате. Нека видим какво имам предвид:
- **Трябва веднага да им зададете стойност** – не се позволяват празни константи!
- **Никога не можете да променяте тази стойност** – JavaScript ще генерира грешка, ако опитате. Нека видим какво имам предвид:
**Проста стойност** - Следното НЕе позволено:
**Проста стойност** - Следното НЕЕ позволено:
```javascript
const PI = 3;
@ -126,11 +200,11 @@ const MY_VARIABLE = 123;
```
**Какво трябва да запомните:**
- **Опитите** за повторно присвояване на константа ще предизвикат грешка
- **Защитава** важни стойности от случайни промени
- **Осигурява** стойността да остане постоянна в програмата ви
- **Опитите** за присвояване на нова стойност на константа ще доведат до грешка
- **Защитава** важни стойности от случайни изменения
- **Гарантира**, че стойността остава постоянна през цялата програма
**Референцията към обект е защитена** - Следното НЕе позволено:
**Защитена е референцията към обекта** - Следното НЕЕ позволено:
```javascript
const obj = { a: 3 };
@ -138,9 +212,9 @@ const MY_VARIABLE = 123;
```
**Разбиране на тези концепции:**
- **Предотвратява** замяната на целия обект с нов
- **Предотвратява** пълната замяна на обектас нов
- **Защитава** референцията към оригиналния обект
- **Запазва** идентичността на обекта в паметта
- **Поддържа** идентичността на обекта в паметта
**Стойността на обекта не е защитена** - Следното Е позволено:
@ -149,65 +223,103 @@ const MY_VARIABLE = 123;
obj.a = 5; // позволено
```
**Разглеждане на случващото се тук:**
- **Модифицира** стойността на свойството вътре в обекта
**Обяснение какво става тук:**
- **Променя** стойността на свойството в обекта
- **Запазва** същата референция към обекта
- **Показва**, че съдържанието на обекта може да се променя, докато референцията остава постоянна
> Забележка,`const` означава, че референцията е защитена от повторно присвояване. Стойността обаче не е_неизменна_ и може да се промени, особено ако е сложна структура като обект.
> Забележка:`const` означава, че референцията е защитена от повторно присвояване. Стойността на обекта обаче не е_непроменяема_ и може да се променя, особено ако е сложна структура като обект.
## Типове данни
JavaScript организира информацията в различни категории, наречени типове данни. Тази концепция наподобява начина, по който древните учени са категоризирали знанията – Аристотел е разграничавал различни видове разсъждения, знаейки, че логическите принципи не могат да се прилагат еднакво към поезия, математика и естествена философия.
JavaScript организира информацията в различни категории, наречени типове данни. Тази концепция отразява начина, по който древните учени категоризирали знанието – Аристотел разграничавал различни видове разсъждения, знаейки, че логическите принципи не могат да се прилагат еднакво към поезия, математика и естествена философия.
Типовете данни са важни, защото различните операции работят с различни видове информация. Точно както не можете да извършите аритметични операции върху нечие име или да подредите по азбучен ред математическо уравнение, JavaScript изисква подходящ тип данни за всяка операция. Разбирането на това предотвратява грешки и прави кода ви по-надежден.
Типовете данни са важни, защото различни операции работят с различни видове информация. Също както не може да извършвате аритметични операции над името на човек или да подреждате математическо уравнение по азбучен ред, JavaScript изисква подходящ тип данни за всяка операция. Разбирането на това предотвратява грешки и прави кода ви по-надежден.
Променливите могат да съхраняват много различни типове стойности, като числа и текст. Тези различни типове стойности са известни като **типове данни**. Типовете данни са важна част от разработката на софтуер, защото помагат на разработчиците да вземат решения как трябва да бъде написан кодът и как трябва да работи софтуерът. Освен това, някои типове данни имат уникални характеристики, които помагат за трансформиране или извличане на допълнителна информация от стойност.
Променливите могат да съхраняват много различни типове стойности, като числа и текст. Тези различни видове стойности се наричат **тип данни**. Типовете данни са важна част от разработката на софтуер, защото помагат на разработчиците да вземат решения как кодът трябва да бъде написан и как трябва да се изпълнява софтуерът. Освен това някои типове данни имат уникални възможности, които помагат да се трансформира или извлече допълнителна информация от дадена стойност.
✅ Типовете данни същосе наричат примитиви на JavaScript, тъй като са най-ниското ниво на типове данни, предоставени от езика. Има 7 примитивни типа данни: string, number, bigint, boolean, undefined, null и symbol. Отделете минута, за да визуализирате какво може да представлява всеки от тези примитиви. Какво е`zebra`? А какво ще кажете за`0`? `true`?
✅ Типовете данни понякогасе наричат примитиви на JavaScript, тъй като са най-ниско ниво типове данни, предоставени от езика. Има 7 примитивни типа данни: string, number, bigint, boolean, undefined, null и symbol. Отделете минута да визуализирате какво може да представлява всеки от тези примитиви. Какво е`зебра`? А`0`? `true`?
### Числа
Числата са най-простият тип данни в JavaScript. Независимо дали работите с цели числа като 42, десетични дроби като 3.14 или отрицателни числа като -5, JavaScript ги обработва еднакво.
Числата са най-простият тип данни в JavaScript. Независимо дали работите със цели числа като 42, десетични като 3.14, или отрицателни числа като -5, JavaScript ги обработва по един и същи начин.
Спомняте ли си нашата променлива от по-рано? Тази 123, която съхранихме, всъщност беше тип данни число:
Помните ли променливата ни от по-рано? Онзи 123, който съхранихме, всъщност беше тип число:
- Можете да извършвате математически операции с тези променливи
- Нее необходима явна декларация на типа
- Нее необходима експлицитна декларация на типа
Променливите могат да съхраняват всички видове числа, включително десетични дроби или отрицателни числа. Числата също могат да сеизползват с аритметични оператори, разгледани в [следващия раздел](../../../../2-js-basics/1-data-types).
Променливите могат да съхраняват всякакви числа, включително десетични или отрицателни. Числата могат да се ползват ис аритметични оператори, разгледани в [следващия раздел](../../../../2-js-basics/1-data-types).
```mermaid
flowchart LR
A["🔢 Числа"] --> B["➕ Събиране"]
A --> C["➖ Изваждане"]
A --> D["✖️ Умножение"]
A --> E["➗ Деление"]
A --> F["📊 Остатък %"]
B --> B1["1 + 2 = 3"]
C --> C1["5 - 3 = 2"]
D --> D1["4 * 3 = 12"]
E --> E1["10 / 2 = 5"]
F --> F1["7 % 3 = 1"]
style A fill:#e3f2fd
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#e0f2f1
style F fill:#fce4ec
```
### Аритметични оператори
Аритметичните оператори ви позволяват да извършвате математически изчисления в JavaScript. Тези оператори следват същите принципи, които математиците са използвали векове наред – същите символи, които се появяват в трудовете на учени като Ал-Хорезми, който е разработил алгебрична нотация.
Аритметичните оператори ви позволяват да извършвате математически изчисления в JavaScript. Тези оператори следват същите принципи, които математиците използват от векове– същите символи, които се появяват в трудовете на учени като Ал-Хорезми, създател на алгебричната нотация.
Операторите работят така, както бихте очаквали от традиционната математика: плюс за събиране, минус за изваждане и т.н.
Операторите работят както е в традиционната математика: плюс за събиране, минус за изваждане и така нататък.
Има няколко типа оператори, които можете да използвате при извършване на аритметични функции, и някои от тях са изброени тук:
Има няколко типа оператори за използване при аритметични операции и някои от тях са изброени тук:
| `+`| **Събиране**: Изчислява сумата на две числа | `1 + 2 //очакван отговор 3` |
| `-`| **Изваждане**: Изчислява разликата на две числа | `1 - 2 //очакван отговор -1` |
| `*`| **Умножение**: Изчислява произведението на две числа | `1 * 2 //очакван отговор 2` |
| `/`| **Деление**: Изчислява частното на две числа | `1 / 2 //очакван отговор 0.5` |
| `%`| **Остатък**: Изчислява остатъка при деление на две числа | `1 % 2 //очакван отговор 1` |
✅ Опитайте! Опитайте аритметична операция в конзолата на браузъра си. Изненадват ли ви резултатите?
✅ Опитайте! Направете аритметична операция в конзолата на браузъра си. Резултатите изненадват ли ви?
### Стрингове
### 🧮 **Проверка на математическите умения: Изчисляване с увереност**
В JavaScript текстовите данни се представят като стрингове. Терминът "стринг" идва от концепцията за символи, свързани заедно в последователност, подобно на начина, по който писарите в средновековните манастири са свързвали букви, за да образуват думи и изречения в своите ръкописи.
**Проверете разбирането си за аритметика:**
- Каква е разликата между `/` (деление) и `%` (остатък)?
- Можете ли да предскажете резултата от `10 % 3`? (Подсказка: не е 3.33...)
- Защо операторът за остатък може да е полезен при програмиране?
Стринговете са основни за уеб разработката. Всеки текст, показан на уебсайт – потребителски имена, етикети на бутони, съобщения за грешки, съдържание –се обработва като стрингови данни. Разбирането на стринговете е от съществено значение за създаването на функционални потребителски интерфейси.
```mermaid
pie title "Използване на операции с числа в JavaScript"
"Събиране (+)" : 35
"Изваждане (-)" : 20
"Умножение (*)" : 20
"Деление (/)" : 15
"Остатък (%)" : 10
```
> **Практичен поглед**: Операторът за остатък (%) е много полезен за проверка дали числа са четни/нечетни, създаване на модели или циклиране през масиви!
Стринговете са набори от символи, които се намират между единични или двойни кавички.
### Низове
В JavaScript текстовите данни се представят чрез низове. Терминът "низа" произлиза от концепцията за поредица от символи, съединени заедно, подобно на начина, по който писарите в средновековните манастири свързвали букви в думи и изречения в техните ръкописи.
Низовете са основополагащи за уеб разработката. Всеки текст, показван на уебсайт – потребителски имена, надписи на бутони, съобщения за грешки, съдържание –се обработва като низ. Разбирането на низовете е ключово за създаване на функционални потребителски интерфейси.
Низовете са поредици от символи, намиращи се между единични или двойни кавички.
```javascript
'This is a string'
@ -215,43 +327,118 @@ let myVariable = 123;
let myString = 'This is a string value stored in a variable';
```
**Разбиране на тези концепции:**
- **Използва** единични кавички `'` или двойни кавички `"` за дефиниране на стрингове
**Разбиране на тези понятия:**
- **Използва** или единични кавички `'`, или двойни кавички `"` за дефиниране на низове
- **Съхранява** текстови данни, които могат да включват букви, числа и символи
- **Присвоява** стрингови стойности на променливи за по-късно използване
- **Изисква** кавички, за да се разграничи текстът от имената на променливите
- **Присвоява** стрингови стойности на променливи за по-късна употреба
- **Изисква** кавички, за да се разграничат текстовите стойности от имена на променливи
Не забравяйте да използвате кавички при писане на низ, в противен случай JavaScript ще приеме, че става дума за име на променлива.
```mermaid
flowchart TD
A["📝 Низове"] --> B["Единични кавички"]
A --> C["Двойни кавички"]
A --> D["Шаблонни литерали"]
B --> B1["'Здравей свят'"]
C --> C1["\"Здравей свят\""]
D --> D1["`Здравей \${name}`"]
E["Операции с низове"] --> F["Конкатенация"]
E --> G["Вмъкване в шаблон"]
E --> H["Дължина и методи"]
F --> F1["'Здравей' + ' ' + 'свят'"]
G --> G1["`Здравей \${firstName} \${lastName}`"]
H --> H1["myString.length"]
style A fill:#e3f2fd
style E fill:#fff3e0
style D fill:#e8f5e8
style G fill:#e8f5e8
```
### Форматиране на низове
Манипулирането на низове ви позволява да съединявате текстови елементи, да включвате променливи и да създавате динамично съдържание, което реагира на състоянието на програмата. Тази техника ви позволява да конструирате текст програмно.
Не забравяйте да използвате кавички, когато пишете стринг, иначе JavaScript ще предположи, че това е име на променлива.
Често трябва да събирате няколко низове заедно – този процес се нарича конкатенация.
За да **обедините** два или повече низа, или да ги свържете заедно, използвайте оператора `+`.
### Форматиране на стрингове
```javascript
let myString1 = "Hello";
let myString2 = "World";
Манипулирането на стрингове ви позволява да комбинирате текстови елементи, да включвате променливи и да създавате динамично съдържание, което реагира на състоянието на програмата. Тази техника ви позволява да създавате текст програмно.
Често се налага да съединявате няколко стринга – този процес се нарича конкатенация.
**Стъпка по стъпка, ето какво се случва:**
- **Обединява** няколко низа, използвайки оператора `+`
- **Свързва** низовете директно без интервали в първия пример
- **Добавя** интервали `" "` между низовете за по-добра четимост
- **Вмъква** пунктуация като запетаи за правилно форматиране
За да **конкатенирате** два или повече стринга, или да ги съедините, използвайте оператора `+`.
✅ Защо в JavaScript `1 + 1 = 2`, но `'1' + '1' = 11?` Помислете. А какво ще кажете за `'1' + 1`?
**Тemplate literals** (шаблонни литерали) са друг начин да форматирате низове, но вместо кавички се използва обратен апостроф. Всичко, което не е обикновен текст, трябва да бъде поставено в плейсхолдъри `${ }`. Това включва и променливи, които могат да са низове.
Можете да постигнете целите си за форматиране с който и да е от методите, но шаблонните литерали ще запазят всички интервали и нови редове.
**Да разберем всяка част:**
- **Използва** обратни апострофи `` ` `` вместо обикновени кавички за създаване на шаблонни литерали
- **Вгражда** променливи директно чрез синтаксиса на плейсхолдъра `${}`
- **Запазва** интервалите и форматирането точно както са написани
- **Предоставя** по-чист начин за създаване на сложни низове с променливи
Можете да постигнете желания ефект с всеки от двата метода, но шаблонните литерали ще уважават всички интервали и прекъсвания на редове.
✅ Кога бихте използвали шаблонен литерал вместо обикновен низ?
### 🔤 **Проверка на уменията за низове: Увереност при манипулиране на текст**
**Оценете уменията си с низове:**
- Можете ли да обясните защо `'1' + '1'`е равно на `'11'`, а не на `2`?
- Кой метод за низове ви се струва по-четим: конкатенация или шаблонни литерали?
- Какво се случва, ако забравите кавичките около низ?
```mermaid
stateDiagram-v2
[*] --> PlainText: "Здравей"
[*] --> Variable: name = "Алиса"
PlainText --> Concatenated: + " " + name
Variable --> Concatenated
PlainText --> Template: `Здравей ${name}`
Variable --> Template
Concatenated --> Result: "Здравей Алиса"
Template --> Result
note right of Concatenated
Традиционен метод
По-подробен
end note
note right of Template
Модерен ES6 синтаксис
По-чист и по-лесен за четене
end note
```
> **Професионален съвет**: Шаблонните литерали обикновено са предпочитани за сложна работа с низове, защото са по-четими и отлично се справят с много редови низове!
### Булеви стойности
Булевите стойности представляват най-простата форма на данни: те могат да съдържат само една от две стойности –`true` или `false`. Тази бинарна логическа система води началото си от работата на Джордж Бул, математик от 19-ти век, който разработва булевата алгебра.
Булевите стойности представляват най-простата форма на данни: те могат да имат само една от две стойности –`true` или `false`. Тази двоична логика води началото си от работата на Джордж Бул, математик от 19 век, който разработва булева алгебра.
Въпреки своята простота, булевите стойности са от съществено значение за логиката на програмите. Те позволяват на вашия код да взема решения въз основа на условия – дали потребителят е влязъл в системата, дали бутон е натиснат или дали са изпълнени определени критерии.
Въпреки своята простота, булевите стойности саосновни за логиката в програмирането. Те позволяват на вашия код да взема решения въз основа на условия –например дали един потребител е влязъл в системата, дали е кликнат бутон или дали определени критерии са изпълнени.
Булевите стойности могат да бъдат само две: `true` или `false`. Те помагат за вземане на решения кои редове код да се изпълнят, когато са изпълнени определени условия. В много случаи [операторите](../../../../2-js-basics/1-data-types) помагат за задаване на стойността на булева променлива и често ще забележите и пишете променливи, които се инициализират или техните стойности се актуализират с оператор.
Булевите стойности могат да са само две: `true` или `false`. Те помагат за вземането на решения кои редове код да се изпълнят при изпълнение на определени условия. В много случаи [операторите](../../../../2-js-basics/1-data-types) помагат при задаване на стойността на булева променлива и често ще видите и пишете променливи, които се инициализират или техните стойности сеобновяват с оператор.
```javascript
let myTrueBool = true;
@ -260,42 +447,172 @@ let myFalseBool = false;
**В горния пример сме:**
- **Създали** променлива, която съхранява булевата стойност `true`
- **Демонстрирали** как да съхраняваме булевата стойност `false`
- **Използвали** точните ключови думи `true` и `false` (без кавички)
- **Показали** как се съхранява булевата стойност `false`
- **Използвали** точните ключови думи `true` и `false` (не са нужни кавички)
- **Подготвили** тези променливи за използване в условни изрази
✅ Променлива може да се счита за 'истинна', ако се оценява като булева стойност `true`. Интересното е, че в JavaScript [всички стойности са истинни, освен ако не са дефинирани като фалшиви](https://developer.mozilla.org/docs/Glossary/Truthy).
✅ Променлива може да се счита за „истинна“ (truthy), ако се оценява като булево `true`. Интересно е, че в JavaScript [всички стойности са truthy, освен ако не са дефинирани като falsy](https://developer.mozilla.org/docs/Glossary/Truthy).
```mermaid
flowchart LR
A["🔘 Булеви Стойности"] --> B["true"]
A --> C["false"]
D["Истинни Стойности"] --> D1["'hello'"]
D --> D2["42"]
D --> D3["[]"]
D --> D4["{}"]
E["Лъжливи Стойности"] --> E1["false"]
E --> E2["0"]
E --> E3["''"]
E --> E4["null"]
E --> E5["undefined"]
E --> E6["NaN"]
style B fill:#e8f5e8
style C fill:#ffebee
style D fill:#e3f2fd
style E fill:#fff3e0
```
### 🎯 **Проверка на булевата логика: Умения за вземане на решения**
**Тествайте разбирането си за булеви стойности:**
- Защо според вас JavaScript има „истински“ (truthy) и „невярни“ (falsy) стойности освен само `true` и `false`?
- Можете ли да предвидите кое от следните е falsy: `0`, `"0"`, `[]`, `"false"`?
- Как булевите стойности могат да бъдат полезни при контролирането на изпълнението на програмата?
```mermaid
pie title "Чести случаи на използване на булеви стойности"
"Условна логика" : 40
"Състояние на потребител" : 25
"Превключватели на функции" : 20
"Валидация" : 15
```
> **Запомнете**: В JavaScript само 6 стойности са falsy: `false`, `0`, `""`, `null`, `undefined` и `NaN`. Всичко останало е truthy!
---
## 📊 **Обобщение на вашия комплект от типове данни**
F["⚡ Ключови Концепции"] --> F1["Типът е важен за операциите"]
F --> F2["JavaScript е динамично типизиран"]
F --> F3["Променливите могат да сменят тип"]
F --> F4["Имената са чувствителни към главни/малки букви"]
style A fill:#e3f2fd
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#e0f2f1
style F fill:#fce4ec
```
## Предизвикателство с GitHub Copilot Agent 🚀
Използвайте режим Agent, за да завършите следното предизвикателство:
Използвайте режим Agent, за да изпълните следното предизвикателство:
**Описание:** Създайте мениджър за лична информация, който демонстрира всички типове данни в JavaScript, които сте научили в този урок, като същевременно обработва сценарии с реални данни.
**Описание:** Създайте мениджър за лична информация, който демонстрира всички типове данни в JavaScript, които сте научили в този урок, докато обработва реални ситуации с данни.
**Задача:** Създайте JavaScript програма, която създава обект за потребителски профил, съдържащ: име на човек (низ), възраст (число), статус на студент (булева стойност), любими цветове като масив и обект за адрес с свойства за улица, град и пощенски код. Включете функции за показване на информацията за профила и актуализиране на отделни полета. Уверете се, че демонстрирате конкатенация на низове, шаблонни литерали, аритметични операции с възрастта и булева логика за студентския статус.
**Задача:** Напишете JavaScript програма, която създава обект с потребителски профил, съдържащ: име на човек (низ), възраст (число), статус на студент (булева стойност), любими цветове като масив и обект адрес с улица, град и пощенски код. Включете функции за показване на профилната информация и актуализиране на отделни полета. Демонстрирайте конкатенация на низове, шаблонни литерали, аритметични операции с възрастта и булева логика за статуса на студент.
Научете повече за [режим Agent](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
Научете повече за [режим agent](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
## 🚀 Предизвикателство
JavaScript има някои поведения, които могат да изненадат разработчиците. Ето един класически пример за изследване: опитайте да въведете това в конзолата на браузъра: `let age = 1; let Age = 2; age == Age` и наблюдавайте резултата. Връща `false`– можете ли да определите защо?
JavaScript има някои поведения, които могат да изненадат разработчиците. Ето класически пример за изследване: опитайте да напишете в конзолата на браузъра си: `let age = 1; let Age = 2; age == Age` и наблюдавайте резултата. Връща `false`– можете ли да разберете защо?
Това представлява едно от многото поведения на JavaScript, които си струва да се разберат. Познаването на тези особености ще ви помогне да пишете по-надежден код и да отстранявате проблеми по-ефективно.
Това представлява едно от множеството поведения на JavaScript, които си струва да се разбират. Познаването на тези особености ще ви помогне да пишете по-надежден код и по-ефективно да отстранявате грешки.
## Тест след лекцията
[Тест след лекцията](https://ff-quizzes.netlify.app)
## Преглед и самостоятелно обучение
Разгледайте [този списък с упражнения по JavaScript](https://css-tricks.com/snippets/javascript/) и опитайте едно. Какво научихте?
Вижте [този списък с JavaScript упражнения](https://css-tricks.com/snippets/javascript/) и опитайте някое. Какво научихте?
## Задача
[Практика с типове данни](assignment.md)
## 🚀 Вашата времева линия за усвояване на JavaScript типове данни
### ⚡ **Какво можете да направите през следващите 5 минути**
- [ ] Отворете конзолата на браузъра и създайте 3 променливи с различни типове данни
- [ ] Опитайте предизвикателството: `let age = 1; let Age = 2; age == Age` и разберете защо е false
- [ ] Практикувайте конкатенация на низове с вашето име и любимо число
- [ ] Тествайте какво се случва, когато добавите число към низ
### 🎯 **Какво можете да постигнете този час**
- [ ] Попълнете теста след урока и прегледайте объркващи концепции
- [ ] Създайте мини калкулатор, който събира, изважда, умножава и дели две числа
- [ ] Направете прост форматиращ низ с помощта на шаблонни литерали
- [ ] Изследвайте разликите между операторите `==` и `===`
- [ ] Практикувайте преобразуване между различните типове данни
### 📅 **Вашата седмична основа в JavaScript**
- [ ] Изпълнете задачата с увереност и креативност
- [ ] Създайте личен профилен обект, използвайки всички научени типове данни
- [ ] Практикувайте с [JavaScript упражнения от CSS-Tricks](https://css-tricks.com/snippets/javascript/)
- [ ] Изградете прост валидатор на формуляри с булева логика
- [ ] Експериментирайте с масиви и обекти (преглед на предстоящи уроци)
- [ ] Присъединете се към JavaScript общност и задавайте въпроси за типовете данни
### 🌟 **Вашата месечна трансформация**
- [ ] Интегрирайте знанията за типове данни в по-големи програми
- [ ] Разберете кога и защо да използвате всеки тип данни в реални приложения
- [ ] Помогнете на други начинаещи да разберат основите на JavaScript
- [ ] Създайте малко приложение за управление на различни типове потребителски данни
- [ ] Изследвайте разширени концепции за типове данни като преобразуване на типове и строго равенство
- [ ] Допринасяйте за open source JavaScript проекти с подобрения в документацията
### 🧠 **Последна проверка на уменията с типове данни**
**Празнувайте основите си в JavaScript:**
- Кой тип данни ви изненада най-много с поведението си?
- Колко удобно се чувствате да обяснявате променливи и константи на приятел?
- Коее най-интересното нещо, което открихте за системата от типове на JavaScript?
- Какво реално приложение си представяте да създадете с тези основи?
```mermaid
journey
title Вашето пътуване към увереност с JavaScript
section Днес
Объркан: 3: You
Любопитен: 4: You
Възбуден: 5: You
section Тази седмица
Практикуване: 4: You
Разбиране: 5: You
Създаване: 5: You
section Следващия месец
Решаване на проблеми: 5: You
Преподаване на други: 5: You
Реални проекти: 5: You
```
> 💡 **Вие вече имате основата!** Разбирането на типовете данни е като да научите азбуката преди да пишете истории. Всеки JavaScript програма, която някога ще напишете, ще използва тези фундаментални концепции. Сега разполагате с градивните блокове за създаване на интерактивни уебсайтове, динамични приложения и решаване на реални проблеми с код. Добре дошли в прекрасния свят на JavaScript! 🎉
---
**Отказ от отговорност**:
Този документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Не носим отговорност за недоразумения или погрешни интерпретации, произтичащи от използването на този превод.
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Отказ от отговорност**:
Този документ е преведен с помощта на AI преводаческа услуга [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стараем за точност, моля имайте предвид, че автоматизираните преводи могат да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Ние не носим отговорност за никакви недоразумения или неправилни тълкувания, произтичащи от използването на този превод.

> Скица от [Tomomi Imura](https://twitter.com/girlie_mac)
## Тест преди лекцията
[Тест преди лекцията](https://ff-quizzes.netlify.app)

> Скетчнот от [Tomomi Imura](https://twitter.com/girlie_mac)
```mermaid
journey
title Вашето приключение с JavaScript функции
section Основи
Синтаксис на функцията: 5: You
Извикване на функции: 4: You
Параметри и аргументи: 5: You
section Разширени концепции
Връщани стойности: 4: You
Стойности по подразбиране: 5: You
Композиция на функции: 4: You
section Модерен JavaScript
Стрелкови функции: 5: You
Анонимни функции: 4: You
Функции от по-висок ред: 5: You
```
## Предварителен тест преди лекцията
[Предварителен тест преди лекцията](https://ff-quizzes.netlify.app)
Писането на един и същ код многократно е едно от най-честите разочарования в програмирането. Функциите решават този проблем, като ви позволяват да опаковате кода в блокове, които могат да се използват многократно. Мислете за функциите като за стандартизирани части, които направиха революция в производствената линия на Хенри Форд – веднъж създадени надеждни компоненти, те могат да се използват навсякъде, където са необходими, без да се налага да се изграждат отново.
Повтарящото се писане на един и същ код е една от най-честите фрустрации в програмирането. Функциите решават този проблем, като ви позволяват да пакетирате код в многократно използваеми блокове. Мислете за функциите като за стандартни части, които направиха производствената линия на Хенри Форд революционна – след като създадете надежден компонент, можете да го използвате навсякъде, без да го изграждате отново от нулата.
Функциите ви позволяват да групирате части от кода, за да можете да ги използвате повторно в цялата програма. Вместо да копирате и поставяте една и съща логика навсякъде, можете да създадете функция веднъж и да я извикате, когато е необходимо. Този подход поддържа кода организиран и прави актуализациите много по-лесни.
Функциите позволяват да свържете части от код, така че да ги използвате многократно в цялата си програма. Вместо да копирате и поставяте една и съща логика навсякъде, можете да създадете функция веднъж и да я извиквате, когато е необходимо. Този подход запазва кода ви организиран и прави актуализациите много по-лесни.
В този урок ще научите как да създавате свои собствени функции, да предавате информация на тях и да получавате полезни резултати обратно. Ще откриете разликата между функции и методи, ще научите съвременни синтактични подходи и ще видите как функциите могат да работят с други функции. Ще изградим тези концепции стъпка по стъпка.
В този урок ще научите как да създавате свои собствени функции, да им подавате информация и да получавате полезни резултати обратно. Ще откриете разликата между функции и методи, ще научите модерни синтактични подходи и ще видите как функциите могат да работят с други функции. Ще изграждаме тези концепции стъпка по стъпка.
[](https://youtube.com/watch?v=XgKsD6Zwvlc "Методи и функции")
> 🎥 Кликнете върху изображението по-горе за видео за методи и функции.
> 🎥 Кликнете върху изображението по-горе за видео за методите и функциите.
> Можете да вземете този урок на [Microsoft Learn](https://docs.microsoft.com/learn/modules/web-development-101-functions/?WT.mc_id=academic-77807-sagibbon)!
```mermaid
mindmap
root((JavaScript Functions))
Основни концепции
Декларация
Традиционен синтаксис
Синтаксис на стрелкова функция
Извикване
Използване на скоби
Скоби са задължителни
Параметри
Входни стойности
Множество параметри
Стойности по подразбиране
Аргументи
Предавани стойности
Могат да бъдат от всякакъв тип
Връщани стойности
Изходни данни
оператор return
Изход от функцията
Използване на резултатите
Запис в променливи
Верижни функции
Разширени шаблони
Функции от по-висок ред
Функции като параметри
Обратни извиквания
Анонимни
Несе изисква име
Вградена дефиниция
```
## Функции
Функцията е самостоятелен блок от код, който изпълнява конкретна задача. Тя капсулира логика, която можете да изпълните, когато е необходимо.
Функцията е самостоятелен блок код, който изпълнява конкретна задача. Тя капсулира логика, която можете да изпълнявате, когато е необходимо.
Вместо да пишете един и същ код многократно в програмата си, можете да го опаковате във функция и да я извикате, когато ви е необходима. Този подход поддържа кода чист и прави актуализациите много по-лесни. Представете си предизвикателството за поддръжка, ако трябваше да промените логика, разпръсната на 20 различни места в кода ви.
Вместо да пишете един и същ код многократно в цялата си програма, можете да го опаковате във функция и да извиквате тази функция винаги, когато ви трябва. Този подход държи кода ви чист и прави актуализациите много по-лесни. Помислете за предизвикателството при поддръжка, ако трябва да промените логика, разпръсната в 20 различни места във вашия код.
Даването на описателни имена на функциите ви е от съществено значение. Добре назована функция ясно комуникира своята цел – когато видите `cancelTimer()`, веднага разбирате какво прави, точно както ясно обозначен бутон ви казва какво ще се случи, когато го натиснете.
Важно е да именувате функциите си описателно. Добре именувана функция ясно комуникира целта си– когато видите `cancelTimer()`, веднага разбирате какво прави, точно както бутон с ясна етикет казва точно какво ще се случи, когато го натиснете.
## Създаване и извикване на функция
Нека разгледаме как да създадем функция. Синтаксисът следва последователен модел:
Да разгледаме как се създава функция. Синтаксисът следва постоянен модел:
```javascript
function nameOfFunction() { // function definition
// function definition/body
function nameOfFunction() { // дефиниция на функция
// дефиниция/тяло на функция
}
```
Нека разгледаме това по-подробно:
Нека го разчупим:
- Ключовата дума `function` казва на JavaScript "Хей, създавам функция!"
- `nameOfFunction`е мястото, където давате на функцията си описателно име
- Скобите `()`са мястото, където можете да добавите параметри (ще стигнем до това скоро)
- Къдравите скоби `{}` съдържат действителния код, който се изпълнява, когато извикате функцията
- `nameOfFunction`е мястото, където давате описателно име на функцията си
- Круглите скоби `()`са където можете да добавите параметри (скоро ще ги разгледаме)
- Фигурните скоби `{}` съдържат реалния код, който се изпълнява, когато извикате функцията
Нека създадем проста функция за поздрав, за да видим това в действие:
@ -59,34 +107,57 @@ function displayGreeting() {
}
```
Тази функция отпечатва "Hello, world!" в конзолата. След като я дефинирате, можете да я използвате толкова пъти, колкото е необходимо.
Тази функция отпечатва "Hello, world!" в конзолата. След като я дефинирате, можете да я използвате колкото пъти ви трябва.
За да изпълните (или "извикате") функцията си, напишете нейното име, последвано от скоби. JavaScript ви позволява да дефинирате функцията си преди или след като я извикате – JavaScript двигателят ще се погрижи за реда на изпълнение.
За да изпълните (или "извикате") функцията си, напишете нейното име, последвано от скоби. JavaScript ви позволява да дефинирате функцията си преди или след като я извикате –двигателят на JavaScript ще се погрижи за реда на изпълнение.
```javascript
// calling our function
// извикване на нашата функция
displayGreeting();
```
Когато изпълните този ред, той изпълнява целия код вътре във функцията `displayGreeting`, показвайки "Hello, world!" в конзолата на браузъра ви. Можете да извиквате тази функция многократно.
> **Note:** През тези уроци сте използвали **методи**. `console.log()`е метод – по същество функция, която принадлежи на обекта `console`. Основната разлика е, че методите са прикрепени към обекти, докато функциите са независими. Много разработчици използват тези термини взаимозаменяемо в ежедневни разговори.
Когато изпълните този ред, се изпълнява целият код вътре във вашата функция `displayGreeting`, който показва "Hello, world!" в конзолата на браузъра ви. Можете да извиквате тази функция многократно.
### 🧠 **Проверка на основите на функциите: Създаване на първите ви функции**
**Да видим как се справяте с основните функции:**
- Можете ли да обясните защо използваме фигурните скоби `{}` при дефиниция на функции?
- Какво се случва, ако напишете `displayGreeting` без скобите?
- Защо бихте искали да извиквате една и съща функция няколко пъти?
```mermaid
flowchart TD
A["✏️ Дефиниране на функция"] --> B["📦 Опаковане на кода"]
B --> C["🏷️ Дайте му име"]
C --> D["📞 Викайте при нужда"]
D --> E["🔄 Използвайте повторно навсякъде"]
F["💡 Предимства"] --> F1["Без повторение на кода"]
F --> F2["Лесна поддръжка"]
F --> F3["Ясна организация"]
F --> F4["По-лесно тестване"]
style A fill:#e3f2fd
style E fill:#e8f5e8
style F fill:#fff3e0
```
> **Забележка:** Вие използвате **методи** през тези уроци. `console.log()`е метод – всъщност функция, която принадлежи на обекта `console`. Ключовата разлика е, че методите са прикачени към обекти, докато функциите са независими. Много разработчици използват тези термини взаимозаменяемо в разговор.
### Най-добри практики за функции
Ето няколко съвета, които ще ви помогнат да пишете страхотни функции:
Ето няколко съвета, за да напишете страхотни функции:
- Давайте на функциите си ясни, описателни имена – бъдещото ви аз ще ви благодари!
- Използвайте **camelCasing** за имена с повече от една дума (като `calculateTotal` вместо `calculate_total`)
- Дръжте всяка функция фокусирана върху изпълнението на една задача добре
- Давайте на функциите си ясни и описателни имена – бъдещото ви “аз” ще ви благодари!
- Използвайте **camelCase** за многословни имена (като `calculateTotal` вместо `calculate_total`)
- Поддържайте всяка функция фокусирана върху изпълнението на една задача добре
## Предаване на информация на функция
## Подаване на информация във функция
Нашата функция `displayGreeting`е ограничена – тя може да показва само "Hello, world!" за всички. Параметрите ни позволяват да направим функциите по-гъвкави и полезни.
Нашата функция `displayGreeting`е ограничена – тя може да покаже само "Hello, world!" на всички. Параметрите ни позволяват да направим функциите по-гъвкави и полезни.
**Параметрите** действат като заместители, където можете да вмъкнете различни стойности всеки път, когато използвате функцията. По този начин една и съща функция може да работи с различна информация при всяко извикване.
**Параметрите** действат като заместители, където можете да вмъквате различни стойности всеки път, когато използвате функцията. По този начин една и съща функция може да работи с различна информация при всяко извикване.
Изброявате параметрите вътре в скобите, когато дефинирате функцията си, като разделяте множество параметри със запетаи:
Параметрите се изписват в скобите при дефиниране на функцията, като при многократно използване се разделят със запетаи:
```javascript
function name(param, param2, param3) {
@ -94,9 +165,9 @@ function name(param, param2, param3) {
}
```
Всеки параметър действа като заместител – когато някой извика вашата функция, той ще предостави действителни стойности, които ще бъдат поставени на тези места.
Всеки параметър действа като заместител – когато някой извика функцията ви, той ще подаде реални стойности, които се поставят на тези места.
Нека актуализираме нашата функция за поздрав, за да приема името на някого:
Нека ъпдейтнем нашата функция за поздрав, за да приема името на някого:
```javascript
function displayGreeting(name) {
@ -105,22 +176,44 @@ function displayGreeting(name) {
}
```
Забележете как използваме обратни кавички (`` ` ``) и `${}` за вмъкване на името директно в съобщението – това се нарича шаблонен литерал и е много удобен начин за създаване на низове със смесени променливи.
Забележете как използваме обратни кавички (`` ` ``) и `${}` да вмъкнем името директно в съобщението – това се нарича template literal и е много удобен начин да се създават низове с променливи вътре.
Сега, когато извикаме функцията си, можем да предадем всяко име:
Сега, когато извикаме функцията, можем да подадем произволно име:
```javascript
displayGreeting('Christopher');
// displays "Hello, Christopher!" when run
// показва "Здрасти, Кристофър!", когато се стартира
```
JavaScript взема низа `'Christopher'`, присвоява го на параметъра `name` и създава персонализираното съобщение "Hello, Christopher!"
JavaScript приема низа `'Christopher'`, присвоява го на параметъра `name` и създава персонализираното съобщение "Hello, Christopher!"
```mermaid
flowchart LR
A["🎯 Извикване на функция"] --> B["📥 Параметри"]
B --> C["⚙️ Тяло на функцията"]
C --> D["📤 Резултат"]
A1["displayGreeting('Alice')"] --> A
B1["име = 'Alice'"] --> B
C1["Шаблонен литерал\n\`Здравей, \${name}!\`"] --> C
D1["'Здравей, Алиса!'"] --> D
E["🔄 Типове параметри"] --> E1["Низове"]
E --> E2["Числа"]
E --> E3["Булеви стойности"]
E --> E4["Обекти"]
E --> E5["Функции"]
style A fill:#e3f2fd
style C fill:#e8f5e8
style D fill:#fff3e0
style E fill:#f3e5f5
```
## Стойности по подразбиране
Какво ще стане, ако искаме да направим някои параметри опционални? Тук идват на помощ стойностите по подразбиране!
Какво, ако искаме някои параметри да са по избор? Тогава идват на помощ стойностите по подразбиране!
Да кажем, че искаме хората да могат да персонализират поздравителната дума, но ако не посочат такава, просто ще използваме "Hello" като резервен вариант. Можете да зададете стойности по подразбиране, като използвате знака за равенство, точно както задавате променлива:
Да кажем, че искаме хората да могат да персонализират думата на поздрав, но ако не посочат такава, ще използваме "Hello" като резервна стойност. Можете да зададете стойности по подразбиране, като използвате знака за равенство, както при задаване на променлива:
```javascript
function displayGreeting(name, salutation='Hello') {
@ -128,35 +221,63 @@ function displayGreeting(name, salutation='Hello') {
}
```
Тук `name` все още е задължителен, но `salutation` има резервна стойност `'Hello'`, ако никой не предостави друга поздравителна дума.
Тук `name` все още е задължителен, но `salutation` има резервна стойност `'Hello'`, ако никой не подаде друга стойност за поздрав.
Сега можем да извикаме тази функция по два различни начина:
Сега можем да извикаме функцията по два начина:
```javascript
displayGreeting('Christopher');
// displays "Hello, Christopher"
// показва "Здравей, Кристофър"
displayGreeting('Christopher', 'Hi');
// displays "Hi, Christopher"
// показва "Здрасти, Кристофър"
```
При първото извикване JavaScript използва стойността по подразбиране "Hello", тъй като не сме посочили поздравителна дума. При второто извикване използва нашето персонализирано "Hi". Тази гъвкавост прави функциите адаптивни към различни сценарии.
При първото извикване JavaScript използва "Hello" по подразбиране, тъй като не сме посочили поздрав. При второто ползваме нашия персонализиран "Hi". Тази гъвкавост прави функциите адаптивни към различни сценарии.
### 🎛️ **Проверка на параметрите: Правене на функции гъвкави**
**Изпробвайте знанията си за параметрите:**
- Каква е разликата между параметър и аргумент?
- Защо стойностите по подразбиране са полезни в реалното програмиране?
- Можете ли да предположите какво става, ако подадете повече аргументи, отколкото параметри?
```mermaid
stateDiagram-v2
[*] --> NoParams: function greet() {}
[*] --> WithParams: function greet(name) {}
[*] --> WithDefaults: function greet(name, greeting='Hi') {}
> **Професионален съвет**: Стойностите по подразбиране правят функциите ви по-лесни за употреба. Потребителите могат бързо да започнат с разумни настройки, но все пак да ги променят при нужда!
## Връщане на стойности
Досега нашите функции просто отпечатваха съобщения в конзолата, но какво ако искате функцията да изчисли нещо и да ви върне резултата?
До момента функциите ни само отпечатват съобщения в конзолата, но какво, ако искате функция да изчисли нещо и да ви върне резултат?
Тук идват **връщаните стойности**. Вместо просто да показва нещо, функцията може да ви върне стойност, която можете да съхраните в променлива или да използвате в други части на кода си.
Тук идват **върнатите стойности**. Вместо просто да показва нещо, функцията може да ви върне стойност, която можете да съхраните в променлива или да използвате в други части от кода.
За да изпратите стойност обратно, използвате ключовата дума `return`, последвана от това, което искате да върнете:
За да върнете стойност, използвате ключовата дума `return`, последвана от това, което искате да върнете:
```javascript
return myVariable;
```
Ето нещо важно: когато функцията достигне израза `return`, тя незабавно спира да работи и изпраща тази стойност обратно на този, който я е извикал.
Важно: когато функция достигне `return`, тя веднага спира изпълнението си и връща тази стойност на този, който я е извикал.
Нека модифицираме нашата функция за поздрав, за да връща съобщението, вместо да го отпечатва:
Нека променим функцията за поздрав така, че да връща съобщението, вместо да го отпечатва:
```javascript
function createGreetingMessage(name) {
@ -165,23 +286,61 @@ function createGreetingMessage(name) {
}
```
Сега, вместо да отпечатва поздрава, тази функция създава съобщението и ни го връща.
Сега вместо да отпечатва поздрав, функцията създава съобщение и ни го връща.
За да използваме върнатата стойност, можем да я съхраним в променлива, точно както всяка друга стойност:
За да използваме върнатата стойност, можем да я съхраним в променлива, както всяка друга стойност:
Сега`greetingMessage` съдържа "Hello, Christopher" и можем да го използваме навсякъде в кода си – за да го покажем на уеб страница, да го включим в имейл или да го предадем на друга функция.
Сега`greetingMessage` съдържа "Hello, Christopher" и можем да я използваме навсякъде в кода – за показване на уебстраница, включване в имейл или предаване на друга функция.
```mermaid
flowchart TD
A["🔧 Обработка на функция"] --> B{"връщащ израз?"}
B -->|Да| C["📤 Върната стойност"]
B -->|Не| D["📭 Върни undefined"]
C --> E["💾 Запазване в променлива"]
C --> F["🔗 Използване в израз"]
C --> G["📞 Предаване на функция"]
D --> H["⚠️ Обикновено не е полезно"]
I["📋 Използване на върнатата стойност"] --> I1["Изчисляване на резултати"]
I --> I2["Проверка на входни данни"]
I --> I3["Трансформация на данни"]
I --> I4["Създаване на обекти"]
style C fill:#e8f5e8
style D fill:#ffebee
style I fill:#e3f2fd
```
### 🔄 **Проверка на върнатите стойности: Получаване на резултати**
**Проверете познанията си за върнатите стойности:**
- Какво се случва с кода след един `return` в функция?
- Защо връщането на стойности е често по-добро от просто отпечатване в конзолата?
- Може ли функция да върне различни типове стойности (низ, число, логическо)?
```mermaid
pie title "Чести типове върнати стойности"
"Низове" : 30
"Числа" : 25
"Обекти" : 20
"Булеви стойности" : 15
"Масиви" : 10
```
> **Важна идея**: Функциите, които връщат стойности, са по-гъвкави, защото извикващият решава какво да прави с резултата. Това прави кода ви по-модулен и многократно използваем!
## Функции като параметри за функции
Функциите могат да бъдат предавани като параметри на други функции. Въпреки че тази концепция може да изглежда сложна в началото, тя е мощна функция, която позволява гъвкави програмни модели.
Функциите могат да бъдат подавани като параметри към други функции. Въпреки че тази идея може да изглежда сложна в началото, тя есилно полезна функция за постигане на гъвкави модели на програмиране.
Този модел е много често срещан, когато искате да кажете "когато нещо се случи, направи това друго нещо." Например, "когато таймерът свърши, изпълни този код" или "когато потребителят натисне бутона, извикай тази функция."
Този модел е много разпространен, когато искате да кажете "когато се случи нещо, направи това". Например "когато таймерът свърши, изпълни този код" или "когато потребителят кликне бутон, извикай тази функция".
Нека разгледаме `setTimeout`, която е вградена функция, която изчаква определено време и след това изпълнява някакъв код. Трябва да й кажем какъв код да изпълни – идеален случай за предаване на функция!
Нека разгледаме `setTimeout`, която е вградена функция, която чака определено време и след това изпълнява някакъв код. Трябва да ѝ кажем какъв код да изпълни – перфектен случай за подаване на функция!
Опитайте този код – след 3 секунди ще видите съобщение:
Забележете как предаваме `displayDone` (без скоби) на `setTimeout`. Не извикваме функцията сами – предаваме я на `setTimeout` и казваме "извикай това след 3 секунди."
Забележете как подаваме `displayDone` (без скоби) на `setTimeout`. Ние не извикваме функцията сами – подаваме я на `setTimeout` и казваме "извикай това след 3 секунди".
### Анонимни функции
Понякога ви е нужна функция само за едно нещо и не искате да й давате име. Помислете – ако използвате функция само веднъж, защо да затрупвате кода сис допълнително име?
Понякога имате нужда от функция за единствена цел и не искате да ѝ давате име. Помислете – ако използвате функция само веднъж, защо да замърсявате кодас допълнително име?
JavaScript ви позволява да създавате **анонимни функции** – функции без имена, които можете да дефинирате точно там, където са ви нужни.
Ето как можем да пренапишем примерас таймера, използвайки анонимна функция:
Ето как можем да пренапишем нашия пример с таймера, използвайки анонимна функция:
```javascript
setTimeout(function() {
@ -209,15 +368,15 @@ setTimeout(function() {
}, 3000);
```
Това постига същия резултат, но функцията е дефинирана директно в извикването на `setTimeout`, което елиминира нуждата от отделна декларация на функция.
Това постига същия резултат, но функцията е дефинирана директно вътре в повикването на `setTimeout`, без нужда от отделна декларация.
### Функции със стрелка
### Стрелкови функции
Съвременният JavaScript предлага още по-кратък начин за писане на функции, наречен **функции със стрелка**. Те използват `=>` (което изглежда като стрелка – разбирате ли?) и са супер популярни сред разработчиците.
Съвременният JavaScript има още по-кратък начин за писане на функции, наречен **стрелкови функции**. Те използват `=>` (което изглежда като стрела– разбирате ли?) и са много популярни сред разработчиците.
Функциите със стрелка ви позволяват да пропуснете ключовата дума `function` и да пишете по-концизен код.
Стрелковите функции ви позволяват да пропуснете ключовата дума `function` и да пишете по-кратък код.
Ето нашия пример с таймера, използвайки функция със стрелка:
Ето нашия пример с таймера, използвайки стрелкова функция:
```javascript
setTimeout(() => {
@ -225,11 +384,64 @@ setTimeout(() => {
}, 3000);
```
`()`е мястото, където биха отишли параметрите (празно в този случай), след това идва стрелката `=>`, и накрая тялото на функцията в къдрави скоби. Това осигурява същата функционалност с по-концизен синтаксис.
### Кога да използвате всяка стратегия
Кога да използвате всеки подход? Практическо правило: ако ще използвате функцията многократно, дайте й име и я дефинирайте отделно. Ако е за една конкретна употреба, обмислете използването на анонимна функция. И двата подхода – функции със стрелка и традиционен синтаксис –са валидни, въпреки че функциите със стрелка са широко разпространени в съвременните JavaScript кодови бази.
`()`е мястото, където биха отишли параметрите (празно в този случай), следва стрелката `=>` и накрая тялото на функцията във фигурни скоби. Това дава същата функционалност с по-сбит синтаксис.
```mermaid
flowchart LR
A["📝 Стилове на функции"] --> B["Традиционен"]
A --> C["Стрелка"]
A --> D["Анонимен"]
B --> B1["function name() {}"]
B --> B2["Вдигнат (Hoisted)"]
B --> B3["Именуван"]
C --> C1["const name = () => {}"]
C --> C2["Кратък синтаксис"]
C --> C3["Модерен стил"]
D --> D1["function() {}"]
D --> D2["Без име"]
D --> D3["Еднократна употреба"]
E["⏰ Кога да използваме"] --> E1["Традиционен: Функции за многократна употреба"]
E --> E2["Стрелка: Кратки callback-и"]
E --> E3["Анонимен: Обработчици на събития"]
style A fill:#e3f2fd
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#e0f2f1
```
### Кога да използвате всеки подход
Кога да изберете всеки метод? Практично ръководство: ако ще използвате функцията многократно, дайте ѝ име и я дефинирайте отделно. Ако е за една конкретна употреба, помислете за анонимна функция. И двата начина – стрелковият синтаксис и традиционният –са валидни, макар че стрелковите функции са по-разпространени в съвременни кодови бази.
### 🎨 **Проверка на стила на функции: Избор на подходящия синтаксис**
**Проверете разбирането си за синтаксиса:**
- Кога бихте предпочели стрелкови функции пред традиционния синтаксис?
- Какво е основното предимство на анонимните функции?
- Можете ли да измислите ситуация, в която именуваната функция е по-добра от анонимна?
```mermaid
quadrantChart
title Матрица за избор на функция
x-axis Просто --> Сложно
y-axis Еднократна употреба --> Многократна употреба
quadrant-1 Функции със стрелки
quadrant-2 Именувани функции
quadrant-3 Анонимни функции
quadrant-4 Традиционни функции
Event Handlers: [0.3, 0.2]
Utility Functions: [0.7, 0.8]
Callbacks: [0.2, 0.3]
Class Methods: [0.8, 0.7]
Mathematical Operations: [0.4, 0.6]
```
> **Модерен тренд**: Стрелковите функции се превръщат в предпочитан избор за много разработчици поради сбития си синтаксис, но традиционните функции все още имат място!
---
@ -237,29 +449,29 @@ setTimeout(() => {
## 🚀 Предизвикателство
Можете ли да обясните с едно изречение разликата между функции и методи? Опитайте!
Можете ли да формулирате с едно изречение разликата между функции и методи? Опитайте!
## Предизвикателствос GitHub Copilot Agent 🚀
## Challengeс GitHub Copilot Agent 🚀
Използвайте режим Agent, за да завършите следното предизвикателство:
Използвайте режим Agent, за да изпълните следното предизвикателство:
**Описание:** Създайте библиотека спомощни математически функции, която демонстрира различни концепции за функции, разгледани в този урок, включително параметри, стойности по подразбиране, връщане на стойности и функции със стрелка.
**Описание:** Създайте библиотека с математически функции, която демонстрира различните концепции за функции, разгледани в този урок, включително параметри, стойности по подразбиране, върнати стойности и стрелкови функции.
**Задача:** Създайте JavaScript файл, наречен`mathUtils.js`, който съдържа следните функции:
**Подсказка:** Създайте JavaScript файл с име`mathUtils.js`, който съдържа следните функции:
1. Функция `add`, която приема два параметъра и връща тяхната сума
2. Функция `multiply` със стойности по подразбиране за параметрите (вторият параметър по подразбиране е 1)
3. Функция със стрелка`square`, която приема число и връща неговия квадрат
4. Функция `calculate`, която приема друга функция като параметър и две числа, след което прилага функцията към тези числа
5. Демонстрирайте извикването на всяка функция с подходящи тестови случаи
3. Стрелкова функция`square`, която приема число и връща квадрата му
4. Функция `calculate`, която приема друга функция като параметър и две числа, след което прилага функцията върху тези числа
5. Демонстриране на извиквания на всяка функция с подходящи тестови случаи
Научете повече за [режим Agent](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
Научете повече за [agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
## Тест след лекцията
[Тест след лекцията](https://ff-quizzes.netlify.app)
## Преглед и самостоятелно обучение
## Преглед и самоподготовка
Струва си [да прочетете малко повече за функциите със стрелка](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Arrow_functions), тъй като те все повече се използват в кодовите бази. Практикувайте писането на функция и след това я пренапишете с този синтаксис.
Струва си да [прочетете малко повече за стрелковите функции](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Arrow_functions), тъй като те все по-често се използват в кодовите бази. Практикувайте да пишете функция, а после да я пренапишете със синтаксиса на стрелковите функции.
## Задача
@ -267,5 +479,105 @@ setTimeout(() => {
---
**Отказ от отговорност**:
Този документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.
## 🧰 **Обобщение на Вашия инструментариум за JavaScript функции**
```mermaid
graph TD
A["🎯 JavaScript Функции"] --> B["📋 Декларация на функция"]
A --> C["📥 Параметри"]
A --> D["📤 Връщани стойности"]
A --> E["🎨 Модерен синтаксис"]
B --> B1["function name() {}"]
B --> B2["Описателно именуване"]
B --> B3["Повторно използваеми блокове код"]
C --> C1["Входни данни"]
C --> C2["Стойности по подразбиране"]
C --> C3["Множество параметри"]
D --> D1["оператор return"]
D --> D2["Изход от функцията"]
D --> D3["Връщане на данни"]
E --> E1["Стрелкови функции: () =>"]
E --> E2["Анонимни функции"]
E --> E3["Функции от по-висок ред"]
F["⚡ Ключови предимства"] --> F1["Повторна използваемост на кода"]
F --> F2["По-добра организация"]
F --> F3["По-лесно тестване"]
F --> F4["Модулен дизайн"]
style A fill:#e3f2fd
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#e0f2f1
style F fill:#fce4ec
```
---
## 🚀 Вашата времева линия за усвояване на JavaScript функции
### ⚡ **Какво можете да направите в следващите 5 минути**
- [ ] Напишете проста функция, която връща любимото ви число
- [ ] Създайте функция с два параметъра, която ги добавя заедно
- [ ] Опитайте да конвертирате традиционна функция в синтаксис на стрелкова функция
- [ ] Практикувайте предизвикателството: обяснете разликата между функции и методи
### 🎯 **Какво можете да постигнете този час**
- [ ] Попълнете теста след урока и прегледайте объркващите концепции
- [ ] Изградете библиотека с математически утилити от предизвикателството на GitHub Copilot
- [ ] Създайте функция, която използва друга функция като параметър
- [ ] Практикувайте писане на функции с параметри по подразбиране
- [ ] Експериментирайте с шаблонни низове в стойностите връщани от функции
### 📅 **Вашето седмично овладяване на функциите**
- [ ] Завършете задачата "Забавление с функции" с креативност
- [ ] Рефакторирайте някакъв повторяем код, който сте написали, във възобновяеми функции
- [ ] Изградете малък калкулатор, използвайки само функции (без глобални променливи)
- [ ] Практикувайте стрелкови функции с методи на масиви като `map()` и `filter()`
- [ ] Създайте колекция от утилити функции за често срещани задачи
- [ ] Изучавайте висшестепенни функции и концепции на функционалното програмиране
### 🌟 **Вашата месечна трансформация**
- [ ] Овладейте напреднали концепции за функции като затваряния и обхват
- [ ] Изградете проект, който силно използва композиция на функции
- [ ] Допринасяйте за отворен код, подобрявайки документацията на функциите
- [ ] Преподавайте на някой друг за функциите и различните стилове на синтаксис
- [ ] Проучете парадигмите на функционалното програмиране в JavaScript
- [ ] Създайте лична библиотека с възобновяеми функции за бъдещи проекти
### 🏆 **Финално чек-ин на шампиона по функции**
**Отбележете вашето овладяване на функциите:**
- Коя е най-полезната функция, която сте създали досега?
- Как изучаването на функциите промени начина, по който мислите за организацията на кода?
- Кой синтаксис на функция предпочитате и защо?
- Какъв реален проблем бихте решили, като напишете функция?
```mermaid
journey
title Вашето развитие на увереността с функции
section Днес
Объркани от синтаксиса: 3: You
Разбиране на основите: 4: You
Писане на прости функции: 5: You
section Тази седмица
Използване на параметри: 4: You
Връщане на стойности: 5: You
Модерен синтаксис: 5: You
section Следващия месец
Съставяне на функции: 5: You
Разширени шаблони: 5: You
Обучение на други: 5: You
```
> 🎉 **Вие овладяхте една от най-мощните концепции в програмирането!** Функциите са градивните елементи на по-големите програми. Всеки апликация, която някога ще създадете, ще използва функции за организиране, повторна употреба и структуриране на кода. Сега разбирате как да пакетиране на логика в възобновяеми компоненти, което ви прави по-ефективен и продуктивен програмист. Добре дошли в света на модулното програмиране! 🚀
---
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Отказ от отговорност**:
Този документ е преведен с помощта на AI преводаческа услуга [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи могат да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Не носим отговорност за каквито и да е недоразумения или неправилни тълкувания, произтичащи от използването на този превод.

> Скетч от [Tomomi Imura](https://twitter.com/girlie_mac)
Чудили ли сте се някога как приложенията вземат интелигентни решения? Например как навигационна система избира най-бързия маршрут или как термостат решава кога да включи отоплението? Това е основната концепция за вземане на решения в програмирането.

> Скетчнот от [Tomomi Imura](https://twitter.com/girlie_mac)
```mermaid
journey
title Вашето приключение с вземането на решения в JavaScript
section Основи
Булеви стойности: 5: You
Оператори за сравнение: 4: You
Логическо мислене: 5: You
section Основни решения
If изявления: 4: You
If-Else логика: 5: You
Switch изявления: 4: You
section Напреднала логика
Логически оператори: 5: You
Сложни условия: 4: You
Тернарни изрази: 5: You
```
Замисляли ли сте се някога как приложенията вземат умни решения? Например как навигационна система избира най-бързия маршрут или как термостатът решава кога да включи отоплението? Това е основната концепция за вземане на решения в програмирането.
Точно както Аналитичната машина на Чарлз Бабидж е била проектирана да следва различни последователности от операции въз основа на условия, съвременните JavaScript програми трябва да правят избори въз основа на различни обстоятелства. Тази способност да се разклонява и да взема решения е това, което превръща статичния код в отзивчиви и интелигентни приложения.
Точно както аналитичният механизъм на Чарлз Бабидж е бил проектиран да следва различни последователности от операции според условия, така и съвременните JavaScript програми трябва да правят избори в зависимост от различни обстоятелства. Тази способност за разклоняване и вземане на решения превръща статичния код в отзивчиви, интелигентни приложения.
В този урок ще научите как да внедрите условна логика във вашите програми. Ще разгледаме условни изрази, оператори за сравнение и логически изрази, които позволяват на вашия код да оценява ситуации и да реагира подходящо.
В този урок ще научите как да прилагате условна логика в своите програми. Ще разгледаме условни изрази, оператори за сравнение и логически изрази, които позволяват на вашия код да оценява ситуации и да реагира по подходящ начин.
Способността да се вземат решения и да се контролира потокът на програмата е основен аспект на програмирането. Тази секция обхваща как да контролирате пътя на изпълнение на вашите JavaScript програми, използвайки булеви стойности и условна логика.
[](https://youtube.com/watch?v=SxTp8j-fMMY "Вземане на решения")
> 🎥 Кликнете върху изображението по-горе за видео относно вземането на решения.
> Можете да преминете този урок на [Microsoft Learn](https://docs.microsoft.com/learn/modules/web-development-101-if-else/?WT.mc_id=academic-77807-sagibbon)!
Способността да вземате решения и да управлявате потока на програмата е основен аспект на програмирането. Този раздел обхваща как да контролирате пътя на изпълнение на вашите JavaScript програми, използвайки булеви стойности и условна логика.
> 🎥 Кликнете върху изображението по-горе за видео за вземане на решения.
> Можете да вземете този урок в [Microsoft Learn](https://docs.microsoft.com/learn/modules/web-development-101-if-else/?WT.mc_id=academic-77807-sagibbon)!
```mermaid
mindmap
root((Вземане на решения))
Boolean Logic
true/false
Резултати от сравнения
Логически изрази
Conditional Statements
if statements
Едно условие
Изпълнение на код
if-else
Два пътя
Алтернативни действия
switch
Множество опции
Чиста структура
Operators
Comparison
=== !== < > <= >=
Връзки между стойности
Logical
&& || !
Комбиниране на условия
Advanced Patterns
Ternary
? : синтаксис
Вградени решения
Complex Logic
Вложени условия
Множество критерии
```
## Кратко припомняне за булевите стойности
Преди да разгледаме вземането на решения, нека си припомним булевите стойности от предишния урок. Наречени на математика Джордж Бул, тези стойности представляват бинарни състояния – или `true`, или `false`. Няма двусмислие, няма средно положение.
Преди да разгледаме вземането на решения, нека си припомним булевите стойности от предишния урок. Кръстени на математика Джордж Бул, тези стойности представляват бинарни състояния – или `true`, или `false`. Няма двусмислия, няма среден вариант.
Тези бинарни стойности са основата на цялата изчислителна логика. Всяко решение, което вашата програма взема, в крайна сметка се свежда до булева оценка.
Тези двоични стойности формират основата на цялата изчислителна логика. Всяко решение, което вашата програма взема, в крайна сметка се свежда до булево оценяване.
Създаването на булеви променливи е лесно:
Създаването на булеви променливи епросто:
```javascript
let myTrueBool = true;
let myFalseBool = false;
```
Това създава две променливи с явни булеви стойности.
Това създава две променливи сизрично зададени булеви стойности.
✅ Булевите стойности са наречени на английския математик, философ и логик Джордж Бул (1815–1864).
✅ Булевите стойности саименувани на английския математик, философ и логик Джордж Бул (1815–1864).
## Оператори за сравнение и булеви стойности
На практика рядко ще задавате булеви стойности ръчно. Вместо това ще ги генерирате, като оценявате условия: "Това число по-голямо ли е от онова?" или "Тези стойности равни ли са?"
В практиката рядко ще задавате булеви стойности ръчно. Вместо това ще ги генерирате чрез оценяване на условия: „Дали това число е по-голямо от онова?“ или „Равни ли са тези стойности?“
Операторите за сравнение позволяват тези оценки. Те сравняват стойности и връщат булеви резултати въз основа на връзката между операндите.
| `<` | **По-малко от**: Сравнява две стойности и връща булевата стойност `true`, ако стойността отляво е по-малка от тази отдясно | `5 < 6 // true` |
| `<=` | **По-малко или равно на**: Сравнява две стойности и връща булевата стойност `true`, ако стойността отляво е по-малка или равна на тази отдясно | `5 <= 6 // true` |
| `>` | **По-голямо от**: Сравнява две стойности и връща булевата стойност `true`, ако стойността отляво е по-голяма от тази отдясно | `5 > 6 // false` |
| `>=` | **По-голямо или равно на**: Сравнява две стойности и връща булевата стойност `true`, ако стойността отляво е по-голяма или равна на тази отдясно | `5 >= 6 // false` |
| `===` | **Строго равенство**: Сравнява две стойности и връща булевата стойност `true`, ако стойностите отдясно и отляво са равни И са от един и същ тип данни. | `5 === 6 // false` |
| `!==` | **Неравенство**: Сравнява две стойности и връща обратната булева стойност на това, което би върнал операторът за строго равенство | `5 !== 6 // true` |
✅ Проверете знанията си, като напишете няколко сравнения в конзолата на браузъра си. Изненадва ли ви някой от върнатите резултати?
| `<` | **По-малко от**: Сравнява две стойности и връща булевата стойност `true`, ако стойността от лявата страна е по-малка от тази от дясната | `5 < 6 // true` |
| `<=` | **По-малко или равно на**: Сравнява две стойности и връща булевата стойност `true`, ако стойността от лявата страна е по-малка или равна на тази отдясно | `5 <= 6 // true` |
| `>` | **По-голямо от**: Сравнява две стойности и връща булевата стойност `true`, ако стойността от лявата страна е по-голяма от тази отдясно | `5 > 6 // false` |
| `>=` | **По-голямо или равно на**: Сравнява две стойности и връща булевата стойност `true`, ако стойността от лявата страна е по-голяма или равна на тази отдясно | `5 >= 6 // false` |
| `===` | **Строго равенство**: Сравнява две стойности и връща булевата стойност `true`, ако стойностите са равни И са от един и същи тип | `5 === 6 // false` |
| `!==` | **Неравенство**: Сравнява две стойности и връща противоположната булева стойност на тази, която би върнал операторът за строго равенство | `5 !== 6 // true` |
✅ Проверете знанията си, като напишете няколко сравнения в конзолата на браузъра. Изненада ли ви някой от върнатите резултати?
```mermaid
flowchart LR
A["🔢 Стойности"] --> B["⚖️ Сравнение"]
B --> C["✅ Булев резултат"]
D["5"] --> E["<6"]
E --> F["вярно"]
G["10"] --> H["=== '10'"]
H --> I["невярно"]
J["'здравей'"] --> K["!== 'свят'"]
K --> L["вярно"]
M["📋 Видове оператори"] --> M1["Равенство: === !=="]
M --> M2["Отношения: < > <= >="]
M --> M3["Строг срещу нестрог"]
style A fill:#e3f2fd
style C fill:#e8f5e8
style M fill:#fff3e0
```
### 🧠 **Проверка на уменията за сравнение: Разбиране на булевата логика**
**Тествайте разбирането си за сравнения:**
- Защо смятате, че `===` (строго равенство) обикновено се предпочита пред `==` (нестрого равенство)?
- Можете ли да предвидите какво връща `5 === '5'`? А`5 == '5'`?
- Каква е разликата между `!==` и `!=`?
```mermaid
stateDiagram-v2
[*] --> Comparison: Две стойности
Comparison --> StrictEqual: === или !==
Comparison --> Relational: < > <= >=
StrictEqual --> TypeCheck: Проверка на тип И стойност
Relational --> NumberCompare: Преобразуване в числа
TypeCheck --> BooleanResult: вярно или невярно
NumberCompare --> BooleanResult
note right of StrictEqual
Предпочитан подход
Без преобразуване на тип
end note
note right of Relational
Полезно за диапазони
Числови сравнения
end note
```
> **Професионален съвет**: Винаги използвайте `===` и `!==` за проверки на равенство, освен ако специално не ви е необходима конверсия на типа. Това предотвратява неочаквано поведение!
## Условен оператор `if`
## If оператор
Операторът `if`е като задаване на въпрос в кода ви. "Ако това условие е вярно, тогава направи това." Вероятно това е най-важният инструмент, който ще използвате за вземане на решения в JavaScript.
Операторът `if`е като да зададете въпрос в кода си. „Ако това условие е вярно, тогава направи това.“ Вероятно това е най-важният инструмент, който ще използвате за вземане на решения в JavaScript.
Ето как работи:
```javascript
if (condition) {
// Condition is true. Code in this block will run.
// Условието е вярно. Кодът в този блок ще се изпълни.
}
```
Условието се поставя в скобите, и ако е`true`, JavaScript изпълнява кода в къдравите скоби. Ако е`false`, JavaScript просто пропуска целия блок.
Условието се поставя в скобите и ако е`true`, JavaScript изпълнява кода в къдриците. Ако е`false`, JavaScript пропуска целия блок.
Често ще използвате оператори за сравнение, за да създадете тези условия. Нека видим практически пример:
Често ще използвате оператори за сравнение, за да създавате тези условия. Нека видим практичен пример:
```javascript
let currentMoney = 1000;
let laptopPrice = 800;
if (currentMoney >= laptopPrice) {
// Condition is true. Code in this block will run.
// Условието е вярно. Кодът в този блок ще се изпълни.
console.log("Getting a new laptop!");
}
```
Тъй като `1000 >= 800`се оценява като `true`, кодът в блока се изпълнява, показвайки "Купувам нов лаптоп!" в конзолата.
## Условен оператор `if..else`
Тъй като `1000 >= 800`се оценява като `true`, кодът вътре в блока се изпълнява и показва "Getting a new laptop!" в конзолата.
```mermaid
flowchart TD
A["🚀 Стартиране на програмата"] --> B{"💰 currentMoney >= laptopPrice?"}
B -->|true| C["🎉 'Взимане на нов лаптоп!'"]
B -->|false| D["⏭️ Пропускане на блок с код"]
C --> E["📋 Продължаване на програмата"]
D --> E
F["📊 Структура на If израза"] --> F1["if (condition) {"]
F1 --> F2[" // код за изпълнение ако е вярно"]
F2 --> F3["}"]
style B fill:#fff3e0
style C fill:#e8f5e8
style D fill:#ffebee
style F fill:#e3f2fd
```
## If..Else оператор
Но какво, ако искате програмата ви да направи нещо различно, когато условието е невярно? Тук идва `else`– това е като резервен план.
Но какво ако искате програмата ви да направи нещо различно, когато условието е`false`? Тук влиза `else`– нещо като резервен план.
Операторът `else` ви дава начин да кажете "ако това условие не е вярно, направи това друго нещо вместо това."
`else` операторът ви дава възможност да кажете „ако това условие не е вярно, направи това друго нещо вместо това.“
```javascript
let currentMoney = 500;
let laptopPrice = 800;
if (currentMoney >= laptopPrice) {
// Condition is true. Code in this block will run.
// Условието е вярно. Кодът в този блок ще се изпълни.
console.log("Getting a new laptop!");
} else {
// Condition is false. Code in this block will run.
// Условието е невярно. Кодът в този блок ще се изпълни.
console.log("Can't afford a new laptop, yet!");
}
```
Сега, тъй като `500 >= 800`е`false`, JavaScript пропуска първия блок и изпълнява блока `else`. Ще видите "Още не мога да си позволя нов лаптоп!" в конзолата.
✅ Тествайте разбирането си за този код и следващия код, като го изпълните в конзолата на браузъра. Променете стойностите на променливите currentMoney и laptopPrice, за да промените върнатия `console.log()`.
Тъй като `500 >= 800`е`false`, JavaScript пропуска първия блок и изпълнява `else` блока вместо това. В конзолата ще видите "Can't afford a new laptop, yet!".
✅ Тествайте разбирането си на този код и следващия, като го изпълните в конзолата на браузъра. Променете стойностите на променливите currentMoney и laptopPrice, за да промените изведеното в `console.log()`.
### 🎯 **Проверка на логиката if-else: Разклонени пътища**
**Оценете разбирането си за условната логика:**
- Какво се случва, ако currentMoney е точно равно на laptopPrice?
- Можете ли да измислите реален сценарий, в който логиката if-else би била полезна?
- Как бихте разширили това, за да обработвате няколко ценови диапазона?
```mermaid
flowchart TD
A["🔍 Оцени условието"] --> B{"Условието вярно ли е?"}
B -->|Да| C["📤 Изпълни IF блока"]
B -->|Не| D["📥 Изпълни ELSE блока"]
C --> E["✅ Избран е един път"]
D --> E
F["🌐 Примери от реалния свят"] --> F1["Статус на влизане"]
F --> F2["Възрастова проверка"]
F --> F3["Валидиране на форма"]
F --> F4["Промени в състоянието на играта"]
style B fill:#fff3e0
style C fill:#e8f5e8
style D fill:#e3f2fd
style F fill:#f3e5f5
```
> **Основна идея**: If-else гарантира, че се избира точно един път. Това осигурява програмата ви винаги да има отговор на всяко условие!
## Оператор `switch`
## Switch оператор
Понякога трябва да сравните една стойност с множество опции. Въпреки че можете да свържете няколко оператора `if..else`, този подход става тромав. Операторът `switch` предоставя по-чиста структура за обработка на множество отделни стойности.
Понякога трябва да сравните една стойност сняколко опции. Въпреки че можете да свържете няколко `if..else` израза, този подход става неудобен. Операторът `switch` осигурява по-чиста структура за обработка на няколко отделни стойности.
Концепцията наподобява механичните системи за превключване, използвани в ранните телефонни централи – една входна стойност определя кой конкретен път ще следва изпълнението.
Концепцията прилича на механичните превключващи системи, използвани в ранните телефонни централи – една входна стойност определя кой конкретен път на изпълнение следва.
```javascript
switch (expression) {
case x:
// code block
// блок с код
break;
case y:
// code block
// блок с код
break;
default:
// code block
// блок с код
}
```
Ето как е структурирано:
Ето как е структуриран:
- JavaScript оценява израза веднъж
- Преглежда всеки `case`, за да намери съвпадение
- Когато намери съвпадение, изпълнява този блок код
- `break` казва на JavaScript да спре и да излезе от switch
- Когато намери съвпадение, изпълнява този кодов блок
- `break` казва на JavaScript да спре и да излезе от switch-а
- Ако няма съвпадение, изпълнява блока `default` (ако има такъв)
```javascript
// Program using switch statement for day of week
// Програма, използваща инструкция switch за ден от седмицата
let dayNumber = 2;
let dayName;
@ -164,72 +310,168 @@ switch (dayNumber) {
console.log(`Today is ${dayName}`);
```
В този пример JavaScript вижда, че `dayNumber`е`2`, намира съответстващия `case 2`, задава `dayName` на "Вторник" и след това излиза от switch. Резултатът? "Днес е вторник" се записва в конзолата.
В този пример JavaScript вижда, че `dayNumber`е`2`, намира съответния `case 2`, задава `dayName` на "Tuesday" и след това излиза от switch-а. Резултатът? В конзолата се изписва "Today is Tuesday".
```mermaid
flowchart TD
A["📥 switch(израз)"] --> B["🔍 Оценка веднъж"]
B --> C{"Съвпада случай 1?"}
C -->|Да| D["📋 Изпълни случай 1"]
C -->|Не| E{"Съвпада случай 2?"}
E -->|Да| F["📋 Изпълни случай 2"]
E -->|Не| G{"Съвпада случай 3?"}
G -->|Да| H["📋 Изпълни случай 3"]
G -->|Не| I["📋 Изпълни по подразбиране"]
D --> J["🛑 прекъсни"]
F --> K["🛑 прекъсни"]
H --> L["🛑 прекъсни"]
J --> M["✅ Изход от switch"]
K --> M
L --> M
I --> M
style A fill:#e3f2fd
style B fill:#fff3e0
style M fill:#e8f5e8
```
✅ Тествайте разбирането си на този код и следващия, като го изпълните в конзолата на браузъра. Променете стойността на променливата a, за да промените изведеното в `console.log()`.
### 🔄 **Майсторство с Switch: Множество опции**
✅ Тествайте разбирането си за този код и следващия код, като го изпълните в конзолата на браузъра. Променете стойностите на променливата a, за да промените върнатия `console.log()`.
**Тествайте разбирането си за switch:**
- Какво се случва, ако забравите оператор `break`?
- Кога бихте използвали `switch` вместо няколко `if-else` оператора?
- Защо `default` случая е полезен, дори ако мислите, че сте покрили всички възможности?
```mermaid
pie title "Кога да използваме всяка структура на решение"
"Прост if-else" : 40
"Сложни if-else вериги" : 25
"Switch изрази" : 20
"Тернарни оператори" : 15
```
> **Добра практика**: Използвайте `switch`, когато сравнявате една променлива с няколко конкретни стойности. Използвайте `if-else` за проверки на диапазони или сложни условия!
## Логически оператори и булеви стойности
Сложните решения често изискват оценка на множество условия едновременно. Точно както булевата алгебра позволява на математиците да комбинират логически изрази, програмирането предоставя логически оператори за свързване на множество булеви условия.
Сложните решения често изискват едновременно оценяване на няколко условия. Точно както булевата алгебра позволява на математиците да комбинират логически изрази, програмирането предлага логически оператори за свързване на множество булеви условия.
Тези оператори позволяват сложна условна логика чрез комбиниране на прости оценки true/false.
Тези оператори дават възможност за усъвършенствана условна логика чрез комбиниране на прости true/false оценки.
| `&&` | **Логическо И**: Сравнява два булеви израза. Връща true **само** ако и двете страни са верни | `(5 > 3) && (5 < 10) // И двете страни са верни. Връща true` |
| `\|\|` | **Логическо ИЛИ**: Сравнява два булеви израза. Връща true, ако поне една страна е вярна | `(5 > 10) \|\| (5 < 10) // Едната страна е невярна, другата е вярна. Връща true` |
| `!` | **Логическо НЕ**: Връща обратната стойност на булев израз | `!(5 > 10) // 5 не е по-голямо от 10, така че "!" го прави вярно` |
| `&&` | **Логическо И**: Сравнява два булеви израза. Връща true **само** ако и двете страни са верни | `(5 > 3) && (5 < 10) // И двете страни са верни. Връща true` |
| `\|\|` | **Логическо ИЛИ**: Сравнява два булеви израза. Връща true, ако поне едната страна е вярна | `(5 > 10) \|\| (5 < 10) // Едната страна егрешна, другата вярна. Връща true` |
| `!` | **Логическо НЕ**: Връща противоположната стойност на булев израз | `!(5 > 10) // 5 не е по-голямо от 10, така че "!" го превръща в true` |
Тези оператори ви позволяват да комбинирате условия по полезни начини:
- И (`&&`) означава, че и двете условия трябва да са верни
- ИЛИ (`||`) означава, че поне едно условие трябва да е вярно
- НЕ (`!`) обръща true на false (и обратно)
- AND (`&&`) означава, че и двете условия трябва да са верни
- OR (`||`) означава, че поне едно от условията трябва да е вярно
Нека видим тези логически оператори в действие с по-реалистичен пример:
Нека видим тези логически оператори в действие чрез по-реалистичен пример:
```javascript
let currentMoney = 600;
let laptopPrice = 800;
let laptopDiscountPrice = laptopPrice - (laptopPrice * 0.2); // Laptop price at 20 percent off
let laptopDiscountPrice = laptopPrice - (laptopPrice * 0.2); // Цена на лаптоп с 20 процента отстъпка
if (currentMoney >= laptopPrice || currentMoney >= laptopDiscountPrice) {
// Condition is true. Code in this block will run.
// Условието е вярно. Кодът в този блок ще се изпълни.
console.log("Getting a new laptop!");
} else {
// Condition is false. Code in this block will run.
// Условието е невярно. Кодът в този блок ще се изпълни.
console.log("Can't afford a new laptop, yet!");
}
```
В този пример: изчисляваме цена с 20% отстъпка (640), след това оценяваме дали наличните ни средства покриват или пълната цена, или цената с отстъпка. Тъй като 600 отговаря на прага за цена с отстъпка от 640, условието се оценява като вярно.
В този пример: изчисляваме 20% отстъпка (640), след това оценяваме дали наличните средства покриват пълната цена ИЛИ цената със 20% отстъпка. Тъй като 600 не покрива намалената цена от 640, условието се оценява като false.
### 🧮 **Проверка на логическите оператори: Комбиниране на условия**
**Тествайте разбирането си за логическите оператори:**
- В израза `A && B`, какво се случва, ако A е false? Оценява ли се изобщо B?
- Можете ли да си представите ситуация, в която трябва да използвате трите оператора (&&, ||, !) заедно?
- Каква е разликата между `!user.isActive` и `user.isActive !== true`?
```mermaid
stateDiagram-v2
[*] --> EvaluateA: A && B
EvaluateA --> CheckB: A е вярно
EvaluateA --> ReturnFalse: A е невярно
CheckB --> ReturnTrue: B е вярно
CheckB --> ReturnFalse: B е невярно
[*] --> EvaluateC: A || B
EvaluateC --> ReturnTrue: A е вярно
EvaluateC --> CheckD: A е невярно
CheckD --> ReturnTrue: B е вярно
CheckD --> ReturnFalse: B е невярно
note right of EvaluateA
Оценка чрез късо съединение:
Ако A е невярно, B никога не се проверява
end note
```
> **Съвет за производителност**: JavaScript използва "short-circuit evaluation" – в `A && B`, ако A е false, B дори не се оценява. Използвайте това във ваша полза!
### Оператор за отрицание
Понякога е по-лесно да мислите за това, когато нещо НЕе вярно. Например вместо да питате "Потребителят влязъл ли е?", може да искате да попитате "Потребителят НЕе ли влязъл?" Операторът за отрицание (`!`) обръща логиката вместо вас.
Понякога е по-лесно да мислите кога нещо не е вярно. Например, вместо да питате „Потребителят влязъл ли е?“, може да искате да попитате „Потребителят не е влязъл ли?“. Операторът удивителен знак (`!`) обръща логиката вместо вас.
```javascript
if (!condition) {
// runs if condition is false
// изпълнява се, ако условието е невярно
} else {
// runs if condition is true
// изпълнява се, ако условието е вярно
}
```
Операторът `!`е като да кажете "обратното на..." – ако нещо е`true`, `!`го прави `false`, и обратно.
Операторът `!`е като да кажете „обратното на...“– ако нещо е`true`, `!`го превръщав `false`, и обратно.
### Тернарни изрази
За прости условни присвоявания JavaScript предоставя **тернарния оператор**. Този кратък синтаксис ви позволява да напишете условен израз в един ред, полезен когато трябва да присвоите една от две стойности въз основа на условие.
За прости условни присвоявания, JavaScript предлага**тернарния оператор**. Този кратък синтаксис ви позволява да напишете условен израз на един ред, полезно когато трябва да зададете една от две стойности в зависимост от условието.
```javascript
let variable = condition ? returnThisIfTrue : returnThisIfFalse;
```
Чете се като въпрос: "Това условие вярно ли е? Ако да, използвай тази стойност. Ако не, използвай онази стойност."
Той се чете като въпрос: „Това условие вярно ли е? Ако да, използвай тази стойност. Ако не, използвай другата стойност.“
Ето един по-осезаем пример:
По-долу е по-ясен пример:
```javascript
let firstNumber = 20;
@ -237,11 +479,11 @@ let secondNumber = 10;
let biggestNumber = firstNumber > secondNumber ? firstNumber : secondNumber;
```
✅ Отделете минута, за да прочетете този код няколко пъти. Разбирате ли как работят тези оператори?
✅ Отделете минута да прочетете този код няколко пъти. Разбирате ли как работят тези оператори?
Ето какво казва този ред: "Първото число по-голямо ли е от второто число? Ако да, постави първото число в biggestNumber. Ако не, постави второто число в biggestNumber."
Тази линия казва: „Дали `firstNumber`е по-голямо от `secondNumber`? Ако да, сложи `firstNumber` в `biggestNumber`. Ако не, сложи `secondNumber` в `biggestNumber`.“
Тернарният оператор е просто по-кратък начин да напишете този традиционен оператор `if..else`:
Тернарният оператор е просто по-кратък начин да се напише традиционният `if..else` израз:
```javascript
let biggestNumber;
@ -252,8 +494,29 @@ if (firstNumber > secondNumber) {
}
```
И двата подхода произвеждат идентични резултати. Тернарният оператор предлага краткост, докато традиционната структура if-else може да бъде по-четима за сложни условия.
И двата подхода произвеждат идентични резултати. Тернарният оператор предлага компактност, докато традиционната if-else структура може да е по-четлива за по-сложни условия.
K["⚡ Кога да се използва"] --> K1["Прости присвоявания"]
K --> K2["Кратки условия"]
K --> K3["Вградени решения"]
K --> K4["Оператори за връщане"]
style A fill:#e3f2fd
style E fill:#fff3e0
style K fill:#e8f5e8
```
---
@ -264,46 +527,146 @@ if (firstNumber > secondNumber) {
---
## Предизвикателство сGitHub Copilot Agent 🚀
## GitHub Copilot Agent Предизвикателство 🚀
Използвайте режим Agent, за да завършите следното предизвикателство:
Използвайте Agent режима, за да изпълните следното предизвикателство:
**Описание:** Създайте цялостен калкулатор за оценки, който демонстрира множество концепции за вземане на решения от този урок, включително оператори if-else, оператори switch, логически оператори и тернарни изрази.
**Описание:** Създайте цялостен калкулатор за оценки, който демонстрира няколко концепции за вземане на решения от този урок, включително if-else оператори, switch оператори, логически оператори и тернарни изрази.
**Задача:** Напишете JavaScript програма, която приема числовата оценка на ученик (0-100) и определя неговата буквена оценка, използвайки следните критерии:
**Подканващ текст:** Напишете JavaScript програма, която приема числова оценка на ученик (0-100) и определя буквена оценка според следните критерии:
- A: 90-100
- B: 80-89
- C: 70-79
- D: 60-69
- F: Под 60
- F: под 60
Изисквания:
1. Използвайте оператор if-else, за да определите буквена оценка
2. Използвайте логически оператори, за да проверите дали ученикът е преминал (оценка >= 60) И има отличен успех (оценка >= 90)
3. Използвайте оператор switch, за да предоставите специфична обратна връзка за всяка буквена оценка
4. Използвайте тернарен оператор, за да определите дали ученикът е допустим за следващия курс (оценка >= 70)
5. Включете проверка на входа, за да се уверите, че оценката е между 0 и 100
1. Използвайте if-else оператор за определяне на буквена оценка
2. Използвайте логически оператори, за да проверите дали студентът е издържал (оценка >= 60) И има отличен успех (оценка >= 90)
3. Използвайте конструкция switch, за да дадете конкретна обратна връзка за всяка буквена оценка
4. Използвайте тернарен оператор, за да определите дали студентът е допустим за следващия курс (оценка >= 70)
5. Включете проверка на входните данни, за да гарантирате, че резултатът е между 0 и 100
Тествайте програмата си с различни резултати, включително гранични случаи като 59, 60, 89, 90 и невалидни входни данни.
Тествайте програмата си с различни оценки, включително гранични случаи като 59, 60, 89, 90 и невалидни входове.
Научете повече за [agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
Научете повече за [режим Agent](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
[Тест след лекцията](https://ff-quizzes.netlify.app/web/quiz/12)
## Review & Self Study
## Преглед и самостоятелно обучение
Прочетете повече за многобройните оператори, налични за потребителя [в MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators).
Прочетете повече за многото налични оператори за потребителя [на MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators).
Прегледайте чудесния [operator lookup](https://joshwcomeau.com/operator-lookup/) на Джош Комо!
Разгледайте чудесния [справочник за оператори на Джош Комо](https://joshwcomeau.com/operator-lookup/)!
## Assignment
## Задание
[Operators](assignment.md)
---
## 🧠 **Обобщение на вашия комплект за вземане на решения**
```mermaid
graph TD
A["🎯 Решения в JavaScript"] --> B["🔍 Логика на булеви стойности"]
A --> C["📊 Условни изрази"]
A --> D["🔗 Логически оператори"]
A --> E["⚡ Напреднали шаблони"]
B --> B1["стойности true/false"]
B --> B2["Оператор за сравнение"]
B --> B3["Концепции за истинност"]
C --> C1["if изрази"]
C --> C2["if-else вериги"]
C --> C3["switch изрази"]
D --> D1["&& (И)"]
D --> D2["|| (ИЛИ)"]
D --> D3["! (НЕ)"]
E --> E1["Тернарен оператор"]
E --> E2["Оценяване с прекъсване"]
E --> E3["Сложни условия"]
F["💡 Ключови принципи"] --> F1["Ясни и четими условия"]
F --> F2["Последователен стил на сравнение"]
F --> F3["Правилен ред на операциите"]
F --> F4["Ефективен ред на оценяване"]
style A fill:#e3f2fd
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#e0f2f1
style F fill:#fce4ec
```
---
[Оператори](assignment.md)
## 🚀 Вашият график за овладяване на вземането на решения в JavaScript
### ⚡ **Какво можете да направите в следващите 5 минути**
- [ ] Практикувайте оператори за сравнение в конзолата на браузъра
- [ ] Напишете прост if-else израз, който проверява възрастта ви
- [ ] Опитайте предизвикателството: пренапишете if-else с помощта на тернарен оператор
- [ ] Тествайте какво се случва с различни "истински" и "фалшиви" стойности
### 🎯 **Какво можете да постигнете този час**
- [ ] Завършете теста след урока и прегледайте объркващите концепции
- [ ] Изградете комплексен калкулатор за оценки от предизвикателството GitHub Copilot
- [ ] Създайте просто решение на дърво за решение за реален сценарий (като избор какво да облечете)
- [ ] Практикувайте комбиниране на множество условия с логически оператори
- [ ] Експериментирайте с switch конструкции за различни случаи на употреба
### 📅 **Вашето овладяване на логиката за седмицата**
- [ ] Завършете задачата с оператори с креативни примери
- [ ] Създайте мини приложение за тест с използване на различни условни структури
- [ ] Направете валидатор за форма, който проверява няколко входни условия
- [ ] Практикувайте упражненията от [operator lookup](https://joshwcomeau.com/operator-lookup/) на Джош Комо
- [ ] Рефакторирайте съществуващия код, за да използва по-подходящи условни структури
- [ ] Учете се на оценки със съкращаване и влияние върху производителността
### 🌟 **Трансформацията ви за месеца**
- [ ] Овладейте сложни вложени условия и запазете четливостта на кода
- [ ] Изградете приложение с усъвършенствана логика за вземане на решения
- [ ] Допринасяйте в open source чрез подобряване на условната логика в съществуващи проекти
- [ ] Обучавайте други за различните условни структури и кога да се използват
- [ ] Проучете функционални подходи към условната логика
- [ ] Създайте личен справочник за най-добри практики в условната логика
### 🏆 **Финална проверка за шампион в вземането на решения**
**Празнувайте овладяването на логическото мислене:**
- Коя е най-сложната логика за вземане на решения, която успешно сте имплементирали?
- Коя условна структура ви се струва най-естествена и защо?
- Как научаването за логическите оператори промени вашия подход към решаването на проблеми?
- Кое приложение в реалния свят биха имали полза от усъвършенствана логика за вземане на решения?
```mermaid
journey
title Вашето развитие на логическото мислене
section Днес
Boolean Confusion: 3: You
If-Else Understanding: 4: You
Operator Recognition: 5: You
section Тази седмица
Complex Conditions: 4: You
Switch Mastery: 5: You
Logical Combinations: 5: You
section Следващия месец
Advanced Patterns: 5: You
Performance Awareness: 5: You
Teaching Others: 5: You
```
> 🧠 **Вие сте овладели изкуството на цифровото вземане на решения!** Всяко интерактивно приложение разчита на условна логика, за да реагира интелигентно на действията на потребителя и променящите се условия. Вече разбирате как да накарате програмите си да мислят, оценяват и избират подходящи отговори. Тази логическа основа ще захрани всяко динамично приложение, което създавате! 🎉
---
**Отказ от отговорност**:
Този документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за каквито и да било недоразумения или погрешни интерпретации, произтичащи от използването на този превод.
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Отговорност**:
Този документ е преведен с използване на AI преводаческа услуга [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматичните преводи могат да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за каквито и да е недоразумения или неправилни интерпретации, произтичащи от използването на този превод.

> Скетч от [Tomomi Imura](https://twitter.com/girlie_mac)
## Предварителен тест
# Основи на JavaScript: Масиви и цикли

> Скетчноут от [Tomomi Imura](https://twitter.com/girlie_mac)
Чудили ли сте се как уебсайтовете следят артикулите в пазарската количка или показват списъка с приятели? Тук идват масивите и циклите. Масивите са като дигитални контейнери, които съхраняват множество парчета информация, докато циклите ви позволяват да работите с тези данни ефективно, без да пишете повтарящ се код.
Някога чудили ли сте се как уебсайтовете следят съдържанието на количката за пазаруване или показват списъка на приятелите ви? Тук влизат в игра масивите и цикълите. Масивите са като дигитални контейнери, които държат множество парчета информация, докато цикълите ви позволяват да работите свсички тези данни ефективно, без да пишете повторен код.
Заедно тези две концепции формират основата за обработка на информация във вашите програми. Ще се научите да преминавате от ръчно изписване на всяка стъпка към създаване на интелигентен, ефективен код, който може да обработва стотици или дори хиляди елементи бързо.
Заедно тези две концепции формират основата за работа с информацията във вашите програми. Ще научите как да преминете от ръчното писане на всяка стъпка до създаването на умен, ефективен код, който може бързо да обработва стотици или дори хиляди елементи.
До края на този урок ще разберете как да изпълнявате сложни задачи с данни само с няколко реда код. Нека разгледаме тези основни програмни концепции.
До края на този урок ще разберете как да изпълнявате сложни задачи с данни с няколко реда код. Нека разгледаме тези основни програмни концепции.
> 🎥 Кликнете върху изображенията по-горе за видеа относно масиви и цикли.
> Можете да вземете този урок на [Microsoft Learn](https://docs.microsoft.com/learn/modules/web-development-101-arrays/?WT.mc_id=academic-77807-sagibbon)!
> 🎥 Кликнете върху изображенията по-горе за видеа за масиви и цикли.
> Можете да вземете този урок в [Microsoft Learn](https://docs.microsoft.com/learn/modules/web-development-101-arrays/?WT.mc_id=academic-77807-sagibbon)!
```mermaid
mindmap
root((Обработка на данни))
Arrays
Structure
Синтаксис с квадратни скоби
Индексиране от нула
Динамичен размер
Operations
push/pop
shift/unshift
indexOf/includes
Types
Масив от числа
Масив от низове
Смесени типове
Loops
For Loops
Брой итерации
Обработка на масиви
Предвидим поток
While Loops
Условно изпълнение
Неизвестен брой итерации
Въвеждане от потребител
Modern Syntax
for...of
forEach
Функционални методи
Applications
Data Analysis
Статистика
Филтриране
Трансформации
User Interfaces
Списъци
Менюта
Галерии
```
## Масиви
Представете си масивите като дигитален шкаф за документи - вместо да съхранявате един документ в едно чекмедже, можете да организирате множество свързани елементи в един структуриран контейнер. В програмния контекст, масивите ви позволяват да съхранявате множество парчета информация в един организиран пакет.
Помислете за масивите като дигитален файлов шкаф – вместо да съхранявате един документ на чекмедже, можете да организирате множество свързани елементи в един структуриран контейнер. В програмирането масивите ви позволяват да съхранявате множество парчета информация в един организиран пакет.
Независимо дали изграждате фото галерия, управлявате списък със задачи или следите високите резултати в игра, масивите предоставят основата за организация на данни. Нека видим как работят.
Независимо дали правите фотогалерия, управлявате списък със задачи или следите високи резултати в игра, масивите осигуряват основата за организация на данните. Нека видим как работят.
✅ Масивите са навсякъде около нас! Можете ли да измислите реален пример за масив, като например масив от слънчеви панели?
✅ Масиви има навсякъде около нас! Можете ли да си представите реален пример за масив, като масив от соларни панели?
### Създаване на масиви
Създаването на масив е супер лесно - просто използвайте квадратни скоби!
Създаването на масив емного просто - просто използвайте квадратни скоби!
```javascript
// Empty array - like an empty shopping cart waiting for items
// Празен масив - като празна количка за пазаруване, чакаща артикули
const myArray = [];
```
**Какво се случва тук?**
Току-що създадохте празен контейнер, използвайки тези квадратни скоби `[]`. Представете си го като празен рафт в библиотека - готов е да съхранява каквито книги искате да организирате там.
Току-що създадохте празен контейнер, използвайки тези квадратни скоби `[]`. Помислете за това като празна библиотечна рафт - готова да държи всички книги, които искате да организирате там.
Можете също така да запълните масива си с начални стойности още от самото начало:
Можете също да напълните вашия масив с начални стойности от самото начало:
// A user's profile info (mixing different types of data)
// Профилна информация на потребител (смесване на различни типове данни)
const userData = ["John", 25, true, "developer"];
// Test scores for your favorite class
// Тестови резултати за вашия любим клас
const scores = [95, 87, 92, 78, 85];
```
**Интересни неща за забелязване:**
- Можете да съхранявате текст, числа или дори стойности истина/лъжа в един и същ масив
- Просто разделете всеки елемент с запетая - лесно!
- Масивите са идеални за съхраняване на свързана информация на едно място
**Готини неща, които да забележите:**
- Можете да съхранявате текст, числа или дори стойности true/false в един и същ масив
- Просто отделете всеки елемент със запетая - лесно е!
- Масивите са перфектни за съхраняване на свързана информация заедно
```mermaid
flowchart LR
A["📦 Масиви"] --> B["Създаване [ ]"]
A --> C["Съхраняване на множество елементи"]
A --> D["Достъп по индекс"]
B --> B1["const arr = []"]
B --> B2["const arr = [1,2,3]"]
C --> C1["Числа"]
C --> C2["Низове"]
C --> C3["Булеви стойности"]
C --> C4["Смесени типове"]
D --> D1["arr[0] = първи"]
D --> D2["arr[1] = втори"]
D --> D3["arr[2] = трети"]
E["📊 Индекс на масива"] --> E1["Индекс 0: Първи"]
E --> E2["Индекс 1: Втори"]
E --> E3["Индекс 2: Трети"]
E --> E4["Индекс n-1: Последен"]
style A fill:#e3f2fd
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#e0f2f1
```
### Индексиране на масиви
Ето нещо, което може да ви се стори необичайно в началото: масивите номерират своите елементи, започвайки от 0, а не от 1. Това номериране, започващо от нула, има своите корени в начина, по който работи компютърната памет - това е програмна конвенция още от ранните дни на езици като C. Всяко място в масива получава свой собствен адресен номер, наречен **индекс**.
Ето нещо, което може да ви се струва необичайно в началото: масивите номерират своите елементи, започвайки от 0, а не от 1. Това индексиране с начало от нула има корени в начина, по който работи компютърната памет – то е програмна конвенция от ранните дни на езици за програмиране като C. Всяко място в масива получава свой собствен адресен номер, наречен **индекс**.
| Индекс | Стойност | Описание |
|-------|-------|-------------|
|--------|----------|----------|
| 0 | "Шоколад" | Първи елемент |
| 1 | "Ягода" | Втори елемент |
| 2 | "Ванилия" | Трети елемент |
| 3 | "Шамфъстък" | Четвърти елемент |
| 4 | "Роки Роуд" | Пети елемент |
| 3 | "Фисташка" | Четвърти елемент |
| 4 | "Роки Род" | Пети елемент |
✅ Изненадва ли ви, че масивите започват от индекс нула? В някои програмни езици индексите започват от 1. Има интересна история за това, която можете [да прочетете в Wikipedia](https://en.wikipedia.org/wiki/Zero-based_numbering).
✅ Изненадва ли ви, че масивите започват с индекс 0? В някои програмни езици индексите започват от 1. Има интересна история по този въпрос, която можете да [прочетете в Wikipedia](https://en.wikipedia.org/wiki/Zero-based_numbering).
const index = fruits.indexOf("banana"); // Връща 1 (позицията на "банан")
const hasApple = fruits.includes("apple"); // Връща true
```
**Разбиране на тези методи:**
- **Добавя** елементи с`push()` (в края) и `unshift()` (в началото)
- **Премахва** елементи с`pop()` (в края) и `shift()` (в началото)
- **Намира** елементи с`indexOf()` и проверява съществуването с`includes()`
- **Връща** полезни стойности като премахнати елементи или индекси на позиции
✅ Опитайте сами! Използвайте конзолата на браузъра си, за да създадете и манипулирате масив по ваш избор.
- **Добавят** елементи с`push()` (в края) и `unshift()` (в началото)
- **Премахват** елементи с`pop()` (в края) и `shift()` (в началото)
- **Намират** елементи с`indexOf()` и проверяват съществуване с`includes()`
- **Връщат** полезни стойности като премахнати елементи или позиционни индекси
✅ Опитайте сами! Използвайте конзолата на браузъра, за да създадете и манипулирате собствен масив.
### 🧠 **Проверка на основите на масива: Организиране на вашите данни**
**Тествайте разбирането си за масиви:**
- Защо мислите, че масивите започват да броят от 0, а не от 1?
- Какво се случва, ако опитате да достъпите индекс, който не съществува (като `arr[100]` в масив с 5 елемента)?
- Можете ли да дадете три реални примера, където масивите биха били полезни?
```mermaid
stateDiagram-v2
[*] --> EmptyArray: const arr = []
EmptyArray --> WithItems: Добавяне на елементи
WithItems --> Accessing: Използване на индекси
Accessing --> Modifying: Промяна на стойности
Modifying --> Processing: Използване на методи
WithItems --> WithItems: push(), unshift()
Processing --> Processing: pop(), shift()
note right of Accessing
Нулирана индексация
arr[0] = първи елемент
end note
note right of Processing
Вградени методи
Динамични операции
end note
```
> **Преглед от реалния свят**: Масивите са навсякъде в програмирането! Фийдове в социални мрежи, колички за пазаруване, фотогалерии, песни в плейлист – всичко е базирано на масиви зад сцената!
## Цикли
Представете си известното наказание от романите на Чарлз Дикенс, където учениците трябваше да пишат едни и същи изречения многократно на дъска. Представете си, че можете просто да кажете на някого "напиши това изречение 100 пъти" и то да бъде направено автоматично. Това е точно, което правят циклите за вашия код.
Циклите са като неуморен помощник, който може да повтаря задачи без грешка. Независимо дали трябва да проверите всеки артикул в пазарска количка или да покажете всички снимки в албум, циклите обработват повторенията ефективно.
JavaScript предлага няколко вида цикли, от които да избирате. Нека разгледаме всеки един и да разберем кога да го използваме.
### Цикъл For
Помислете за известната наказателна практика от романите на Чарлз Дикенс, при която учениците трябвало да пишат редове многократно на шрифт. Представете си, че просто можете да кажете на някого "напиши това изречение 100 пъти" и то да бъде изпълнено автоматично. Това е точно това, което правят цикълите за вашия код.
Циклите са като неуморен помощник, който може да повтаря задачи без грешки. Независимо дали трябва да проверите всеки артикул в количката за пазаруване, или да покажете всички снимки в албум, цикълите обработват повторението ефективно.
JavaScript предоставя няколко вида цикли за избор. Нека разгледаме всеки и разберем кога да ги използваме.
```mermaid
flowchart TD
A["🔄 Видове цикли"] --> B["Цикъл For"]
A --> C["Цикъл While"]
A --> D["Цикъл For...of"]
A --> E["Метод forEach"]
B --> B1["Известен брой итерации"]
B --> B2["Базиран на брояч"]
B --> B3["for(init; condition; increment)"]
C --> C1["Неизвестен брой итерации"]
C --> C2["Базиран на условие"]
C --> C3["while(condition)"]
D --> D1["Модерен ES6+"]
D --> D2["Итерация по масив"]
D --> D3["for(item of array)"]
E --> E1["Функционален стил"]
E --> E2["Метод на масив"]
E --> E3["array.forEach(callback)"]
F["⏰ Кога да се използва"] --> F1["For: Броене, индекси"]
F --> F2["While: Въвеждане от потребител, търсене"]
F --> F3["For...of: Просто итериране"]
F --> F4["forEach: Функционално програмиране"]
style A fill:#e3f2fd
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#e0f2f1
style F fill:#fce4ec
```
### For цикъл
Цикълът `for`е като настройване на таймер - знаете точно колко пъти искате нещо да се случи. Той е супер организиран и предсказуем, което го прави идеален, когато работите с масиви или трябва да броите неща.
`for` цикълът е като да зададете таймер – знаете точно колко пъти искате нещо да се случи. Той е много организиран и предсказуем, което го прави перфектен, когато работите с масиви или трябва да броите неща.
**Структура на цикъл For:**
**Структура на For цикъла:**
| Компонент | Цел | Пример |
|-----------|---------|----------|
| **Инициализация** | Задава начална точка | `let i = 0` |
|-----------|------|--------|
| **Инициализация** | Задава началната точка | `let i = 0` |
| **Условие** | Кога да продължи | `i < 10` |
| **Инкремент** | Как да се актуализира | `i++` |
| **Увеличение** | Как да се актуализира | `i++` |
@ -194,33 +343,59 @@ for (let i = 0; i < testScores.length; i++) {
```
**Стъпка по стъпка, ето какво се случва:**
- **Инициализира** променливата брояч `i` на 0 в началото
- **Инициализира** брояча`i` на 0 в началото
- **Проверява** условието `i < 10` преди всяка итерация
- **Изпълнява** блока код, когато условието е вярно
- **Увеличава** `i`с 1 след всяка итерация с`i++`
- **Спира**, когато условието стане невярно (когато `i` достигне 10)
✅ Стартирайте този код в конзолата на браузъра. Какво се случва, когато направите малки промени в брояча, условието или израза за итерация? Можете ли да го накарате да работи обратно, създавайки обратно броене?
- **Увеличава** `i`с 1 след всяка итерация чрез `i++`
- **Спира** когато условието стане невярно (когато `i` достигне 10)
✅ Стартирайте този код в конзолата на браузъра. Какво се случва, ако направите малки промени в брояча, условието или израза за итерация? Можете ли да го накарате да върви назад, създавайки броене назад?
### 🗓️ **Проверка на усвояването на For цикъл: Контролирано повторение**
**Оценете разбирането си за for цикъла:**
- Кои са трите части на for цикъла и какво прави всяка?
- Как бихте обходили масив в обратен ред?
- Какво се случва, ако забравите частта за увеличаване (`i++`)?
```mermaid
flowchart TD
A["🚀 Стартиране на цикъл For"] --> B["Инициализация: let i = 0"]
> **Мъдрост за цикъла**: For цикли са перфектни, когато знаете точно колко пъти трябва да повторите нещо. Теса най-често използваните за обработка на масиви!
### Цикъл While
### While цикъл
Цикълът `while`е като да кажете "продължавай да правиш това, докато..." - може да не знаете точно колко пъти ще се изпълни, но знаете кога да спрете. Той е идеален за неща като искане на вход от потребителя, докато не получите това, което ви трябва, или търсене в данни, докато не намерите това, което търсите.
`while` цикълъте като да кажете "продължавай да правиш това, докато..." - може да не знаете точно колко пъти ще се изпълни, но знаете кога да спре. Той е идеален за неща като искане за въвеждане от потребител, докато не получи необходимата стойност, или търсене в данни, докато не намерите търсеното.
**Характеристики на цикъл While:**
- **Продължава** изпълнението, докато условието е вярно
- **Изисква** ръчно управление на всякакви променливи броячи
**Характеристики на While цикъла:**
- **Продължава** да изпълнява, докато условието е вярно
- **Изисква** ръчно управление на броячите
- **Проверява** условието преди всяка итерация
- **Рискува** безкрайни цикли, ако условието никога не стане невярно
```javascript
// Basic counting example
// Основен пример за броене
let i = 0;
while (i <10){
console.log(`While count: ${i}`);
i++; // Don't forget to increment!
i++; // Не забравяйте да увеличавате!
}
// More practical example: processing user input
// По-практичен пример: обработка на потребителски вход
let userInput = "";
let attempts = 0;
const maxAttempts = 3;
@ -236,82 +411,140 @@ if (attempts >= maxAttempts) {
```
**Разбиране на тези примери:**
- **Управлява** променливата брояч `i` ръчно вътре в тялото на цикъла
- **Увеличава** брояча, за да предотврати безкрайни цикли
- **Демонстрира** практически случай на употреба с вход от потребителя и ограничаване на опитите
- **Включва** механизми за безопасност за предотвратяване на безкрайно изпълнение
- **Управлява** брояча `i` ръчно в тялото на цикъла
- **Увеличава** брояча, за да предотврати безкраен цикъл
- **Демонстрира** практическо използване с въвеждане от потребител и ограничение на опити
- **Включва** механизми за безопасност срещу безкрайно изпълнение
### ♾️ **Проверка на мъдростта на While цикъла: Повторение базирано на условие**
**Тествайте разбирането си за while цикъла:**
- Каква е основната опасност при използване на while цикли?
- Кога бихте избрали while пред for цикъл?
- Как може да предотвратите безкрайни цикли?
```mermaid
flowchart LR
A["🔄 While срещу For"] --> B["While цикъл"]
A --> C["For цикъл"]
B --> B1["Неизвестен брой итерации"]
B --> B2["Условно управляван"]
B --> B3["Въвеждане от потребител, търсене"]
B --> B4["⚠️ Рискове: безкрайни цикли"]
C --> C1["Известен брой итерации"]
C --> C2["Брояч управляван"]
C --> C3["Обработка на масив"]
C --> C4["✅ Безопасен: предвидим край"]
D["🛡️ Съвети за безопасност"] --> D1["Винаги променяйте променливата на условието"]
D --> D2["Включете условия за изход"]
D --> D3["Задайте максимален брой итерации"]
style A fill:#e3f2fd
style B fill:#fff3e0
style C fill:#e8f5e8
style D fill:#ffebee
```
> **Безопасността преди всичко**: While цикли са мощни, но изискват внимателно управление на условието. Винаги се уверявайте, че условието на цикъла в крайна сметка ще стане невярно!
### Съвременни алтернативи на цикли
### Модерни алтернативи на цикли
JavaScript предлага съвременен синтаксис за цикли, който може да направи кода ви по-четим и по-малко податлив на грешки.
JavaScript предлага модерни синтаксиси за цикли, които правят кода ви по-четим и по-малко податлив на грешки.
- **Изпълнява** функция за всеки елемент от масива
- **Осигурява** както стойността на елемента, така и индекса като параметри
- **Не може** да бъде спрян преждевременно (за разлика от традиционните цикли)
**Какво е полезно да знаете за forEach:**
- **Изпълнява** дадена функция за всеки елемент от масива
- **Предоставя** както стойност, така и индекс като параметри
- **Не може** да бъде прекъснат преждевременно (за разлика от традиционните цикли)
- **Връща** undefined (не създава нов масив)
✅ Защо бихте избрали цикъл for вместо цикъл while? 17 хиляди зрители имаха същия въпрос в StackOverflow, и някои от мненията [може да ви бъдат интересни](https://stackoverflow.com/questions/39969145/while-loops-vs-for-loops-in-javascript).
✅ Защо бихте избрали for цикъл пред while? 17 000 потребители във StackOverflow са имали същия въпрос и някои от мненията [могат да ви бъдат интересни](https://stackoverflow.com/questions/39969145/while-loops-vs-for-loops-in-javascript).
### 🎨 **Проверка на модерния синтаксис на цикли: Възприемане на ES6+**
**Оценете разбирането си за съвременния JavaScript:**
- Какви са предимствата на `for...of` спрямо традиционните for цикли?
- Кога бихте предпочели традиционния for цикъл?
- Каква е разликата между `forEach` и `map`?
```mermaid
quadrantChart
title Ръководство за избор на цикъл
x-axis Традиционен --> Модерен
y-axis Прост --> Сложен
quadrant-1 Модерен Сложен
quadrant-2 Традиционен Сложен
quadrant-3 Традиционен Прост
quadrant-4 Модерен Прост
Traditional For: [0.2, 0.7]
While Loop: [0.3, 0.6]
For...of: [0.8, 0.3]
forEach: [0.9, 0.4]
Array Methods: [0.8, 0.8]
```
> **Модерен тренд**: Синтаксисът ES6+ като `for...of` и `forEach` става предпочитан за итерация на масиви, защото е по-четим и по-малко податлив на грешки!
## Цикли и масиви
Комбинирането на масиви с цикли създава мощни възможности за обработка на данни. Тази комбинация е основна за много програмни задачи, от показване на списъци до изчисляване на статистики.
Комбинирането на масиви с цикли създава мощни възможности за обработка на данни. Това съчетание е фундаментално за много програмни задачи – от показване на списъци до изчисляване на статистики.
- **Инициализира** променливи за проследяване на сума и екстремни стойности
- **Инициализира** променливи за сума и екстремуми
- **Обработва** всяка оценка с един ефективен цикъл
- **Натрупва** общата сума за изчисление на средната стойност
- **Проследява** най-високите и най-ниските стойности по време на итерацията
- **Изчислява** крайните статистики след завършване на цикъла
✅ Експериментирайте с цикли върху масив, който сами сте създали, в конзолата на браузъра.
- **Натрупва** общата сума за изчисляване на средно
- **Следи** най-високите и най-ниските стойности по време на итерацията
- **Изчислява** крайни статистики след приключване на цикъла
✅ Експериментирайте с обхождане на собствен масив в конзолата на браузъра.
```mermaid
flowchart TD
A["📦 Масив с данни"] --> B["🔄 Обработка с цикъл"]
B --> C["📈 Резултати"]
A1["[85, 92, 78, 96, 88]"] --> A
B --> B1["Изчисли общо"]
B --> B2["Намери мин/макс"]
B --> B3["Брой условия"]
B --> B4["Трансформирай данни"]
C --> C1["Средно: 87.8"]
C --> C2["Най-високо: 96"]
C --> C3["Успешни: 5/5"]
C --> C4["Оценки с букви"]
D["⚡ Шаблони за обработка"] --> D1["Натрупване (сумарно)"]
D --> D2["Сравнение (мин/макс)"]
D --> D3["Филтриране (условия)"]
D --> D4["Отразяване (трансформация)"]
style A fill:#e3f2fd
style B fill:#fff3e0
style C fill:#e8f5e8
style D fill:#f3e5f5
```
---
## Предизвикателство с GitHub Copilot Agent 🚀
## Предизвикателство GitHub Copilot Agent 🚀
Използвайте режим Agent, за да завършите следното предизвикателство:
Използвайте Agent режима, за да изпълните следното предизвикателство:
**Описание:** Създайте цялостна функция за обработка на данни, която комбинира масиви и цикли, за да анализира набор от данни и да генерира значими прозрения.
**Описание:** Създайте изчерпателна функция за обработка на данни, която комбинира масиви и цикли за анализ на набор от данни и генериране на смислени изводи.
**Задача:** Създайте функция, наречена `analyzeGrades`, която приема масив от обекти с оценки на ученици (всеки съдържащ свойства name и score) и връща обект със статистики, включително най-висока оценка, най-ниска оценка, средна оценка, брой ученици, които са издържали (score >= 70), и масив с имената на учениците, които са получили над средната оценка. Използвайте поне два различни типа цикли в решението си.
**Задача:** Напишете функция на име`analyzeGrades`, която приема масив от обекти с оценки на студенти (всеки съдържащ свойства име и оценка) и връща обект със статистики, включително най-висока оценка, най-ниска оценка, средна оценка, брой на студенти, които са успели (оценка >= 70), и масив с имената на студентите, които са над средно. Използвайте поне два различни вида цикли в решението си.
Научете повече за [режим Agent](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
Научете повече за [agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
## 🚀 Предизвикателство
JavaScript предлага няколко модерни метода за масиви, които могат да заменят традиционните цикли за конкретни задачи. Разгледайте [forEach](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach), [for-of](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/for...of), [map](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/map), [filter](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) и [reduce](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce).
JavaScript предлага няколко съвременни методи за масиви, които могат да заменят традиционните цикли за специфични задачи. Разгледайте [forEach](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach), [for-of](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/for...of), [map](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/map), [filter](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/filter), и [reduce](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce).
**Вашето предизвикателство:** Преработете примера с оценките на учениците, използвайки поне три различни метода за масиви. Забележете колко по-чист и четим става кодът с модерния синтаксис на JavaScript.
**Вашето предизвикателство:** Рефакторирайте примера с оценките на студентите, използвайки поне три различни метода за масиви. Забележете колко по-чист и четим става кодът с модерния JavaScript синтаксис.
## Тест след лекцията
[Тест след лекцията](https://ff-quizzes.netlify.app/web/quiz/14)
## Куиз след лекцията
[Куиз след лекцията](https://ff-quizzes.netlify.app/web/quiz/14)
## Преглед и самостоятелно обучение
Масивите в JavaScript имат много методи, които са изключително полезни за манипулация на данни. [Прочетете за тези методи](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array) и опитайте някои от тях (като push, pop, slice и splice) върху масив, който сами сте създали.
Масивите в JavaScript имат много методи, които са изключително полезни за манипулация на данни. [Прочетете за тези методи](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array) и изпробвайте някои от тях (като push, pop, slice и splice) върху масив по ваш избор.
## Задание
## Задача
[Цикъл на масив](assignment.md)
[Обход на масив](assignment.md)
---
## 📊 **Обобщение на Вашия набор от инструменти за масиви и цикли**
```mermaid
graph TD
A["🎯 Мастерство с масиви и цикли"] --> B["📦 Основи на масивите"]
A --> C["🔄 Видове цикли"]
A --> D["🔗 Обработка на данни"]
A --> E["🎨 Модерни техники"]
B --> B1["Създаване: [ ]"]
B --> B2["Индексиране: arr[0]"]
B --> B3["Методи: push, pop"]
B --> B4["Свойства: length"]
C --> C1["For: Познати итерации"]
C --> C2["While: Условни"]
C --> C3["For...of: Директен достъп"]
C --> C4["forEach: Функционален"]
D --> D1["Изчисляване на статистики"]
D --> D2["Трансформация на данни"]
D --> D3["Филтриране и търсене"]
D --> D4["Обработка в реално време"]
E --> E1["Стрелкови функции"]
E --> E2["Верижно използване на методи"]
E --> E3["Деструктуриране"]
E --> E4["Шаблонни литерали"]
F["💡 Ключови ползи"] --> F1["Ефективна обработка на данни"]
F --> F2["Намалено повторение на код"]
F --> F3["Разширяеми решения"]
F --> F4["По-чист синтаксис"]
style A fill:#e3f2fd
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#e0f2f1
style F fill:#fce4ec
```
---
## 🚀 Вашият път към майсторство с масиви и цикли
### ⚡ **Какво можете да направите през следващите 5 минути**
- [ ] Създайте масив с любимите си филми и достъпете конкретни елементи
- [ ] Напишете for цикъл, който брои от 1 до 10
- [ ] Опитайте предизвикателството с модерните методи за масиви от урока
- [ ] Практикувайте индексиране на масиви във вашата конзола на браузъра
### 🎯 **Какво можете да постигнете през този час**
- [ ] Попълнете куиза след урока и прегледайте всички затрудняващи ви концепции
- [ ] Изградете комплексния анализатор на оценки от предизвикателството на GitHub Copilot
- [ ] Създайте прост пазарски кош за добавяне и премахване на артикули
- [ ] Практикувайте конвертиране между различни типове цикли
- [ ] Експериментирайте с методи за масиви като `push`, `pop`, `slice` и `splice`
### 📅 **Вашето седмично пътешествие в обработката на данни**
- [ ] Завършете задачата "Обход на масив" с творчески подобрения
- [ ] Изградете приложение за списък със задачи, използвайки масиви и цикли
- [ ] Създайте прост калкулатор за статистически данни
- [ ] Практикувайте с [MDN методи за масиви](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)
- [ ] Изградете галерия за снимки или интерфейс за музикални плейлисти
- [ ] Изследвайте функционалното програмиране с`map`, `filter` и `reduce`
### 🌟 **Вашата месечна трансформация**
- [ ] Усъвършенствайте напредналите операции с масиви и оптимизация на производителността
- [ ] Изградете пълен табло за визуализация на данни
- [ ] Допринасяйте към проекти с отворен код, свързани с обработка на данни
- [ ] Обучете друг някой за масиви и цикли с практически примери
- [ ] Създайте лична библиотека с повторно използваеми функции за обработка на данни
- [ ] Изследвайте алгоритми и структури от данни, базирани на масиви
### 🏆 **Краен контролен списък за шампион по обработка на данни**
**Празнувайте вашето майсторство с масиви и цикли:**
- Коя е най-полезната операция с масив, която сте научили за реални приложения?
- Кой тип цикъл ви се струва най-естествен и защо?
- Как разбирането на масиви и цикли промени вашия подход към организацията на данни?
- Каква сложна задача за обработка на данни бихте искали да решите следваща?
```mermaid
journey
title Вашата еволюция в обработката на данни
section Днес
Array Confusion: 3: You
Loop Basics: 4: You
Index Understanding: 5: You
section Тази седмица
Method Mastery: 4: You
Efficient Processing: 5: You
Modern Syntax: 5: You
section Следващия месец
Complex Algorithms: 5: You
Performance Optimization: 5: You
Teaching Others: 5: You
```
> 📦 **Отключихте силата на организацията и обработката на данни!** Масивите и циклите са основата на почти всяко приложение, което ще изграждате. От прости списъци до сложен анализ на данни - вече имате инструментите за работа с информацията ефективно и елегантно. Всяка динамична уеб страница, мобилно приложение и приложение, базирано на данни, разчита на тези основни концепции. Добре дошли в света на мащабируемата обработка на данни! 🎉
---
**Отказ от отговорност**:
Този документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Не носим отговорност за недоразумения или погрешни интерпретации, произтичащи от използването на този превод.
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Отказ от отговорност**:
Този документ е преведен с помощта на AI преводаческа услуга [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля имайте предвид, че автоматичните преводи могат да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за всякакви недоразумения или неправилни тълкувания, произтичащи от използването на този превод.

> Скица от [Tomomi Imura](https://twitter.com/girlie_mac)
HTML, или HyperText Markup Language, е основата на всеки уебсайт, който някога сте посещавали. Можете да си представите HTML като скелета, който дава структура на уеб страниците – той определя къде се намира съдържанието, как е организирано и какво представлява всяка част. Докато CSS по-късно ще "облече" вашия HTML с цветове и оформления, а JavaScript ще го оживи с интерактивност, HTML предоставя основната структура, която прави всичко останало възможно.
В този урок ще създадете HTML структура за интерфейс на виртуален терариум. Този практически проект ще ви научи на основни концепции на HTML, докато изграждате нещо визуално привлекателно. Ще научите как да организирате съдържание, използвайки семантични елементи, да работите с изображения и да създавате основата за интерактивно уеб приложение.
До края на този урок ще имате работеща HTML страница, която показва изображения на растения, организирани в колони, готова за стилизиране в следващия урок. Несе притеснявайте, ако изглежда основно в началото – точно това трябва да прави HTML, преди CSS да добави визуалния блясък.
# Terrarium Project Part 1: Въведение в HTML
```mermaid
journey
title Вашето пътуване за изучаване на HTML
section Основи
Създаване на HTML файл: 3: Student
Добавяне на DOCTYPE: 4: Student
Структуриране на документа: 5: Student
section Съдържание
Добавяне на метаданни: 4: Student
Включване на изображения: 5: Student
Организиране на оформлението: 5: Student
section Семантика
Използване на правилни тагове: 4: Student
Подобряване на достъпността: 5: Student
Създаване на терариум: 5: Student
```

> Скетчноут от [Tomomi Imura](https://twitter.com/girlie_mac)
HTML или HyperText Markup Language е основата на всеки уебсайт, който някога сте посещавали. Помислете за HTML като за скелета, който дава структура на уеб страниците – той определя къде да отиде съдържанието, как е организирано и какво представлява всяка част. Докато CSS по-късно „облича“ вашия HTML с цветове и оформления, а JavaScript го оживява с интерактивност, HTML осигурява съществената структура, която прави всичко останало възможно.
В този урок ще създадете HTML структура за виртуален интерфейс на терариум. Този практически проект ще ви научи на основни концепции в HTML, докато изграждате нещо визуално ангажиращо. Ще научите как да организирате съдържание с помощта на семантични елементи, да работите с изображения и да създадете основата за интерактивно уеб приложение.
Към края на урока ще имате работеща HTML страница, показваща изображения на растения, организирани в колони, готова за стилове в следващия урок. Несе притеснявайте, ако първоначално изглежда основно – това е точно това, което HTML трябва да прави преди CSS да добави визуален блясък.
Преди да се потопим в HTML кода, нека създадем подходящо работно пространство за вашия проект за терариум. Създаването на организирана структура на файловете от самото начало е важен навик, който ще ви служи добре през цялото ви пътешествие в уеб разработката.
Преди да се потопим в HTML кода, нека настроим подходящо работно пространство за вашия терариум проект. Създаването на организирана файловата структура от самото начало е важен навик, който ще ви служи през цялото ви пътешествие в уеб разработката.
### Задача: Създайте структурата на проекта
### Задача: Създайте структурата на проекта си
Ще създадете специална папка за вашия проект за терариум и ще добавите първия си HTML файл. Ето два подхода, които можете да използвате:
Ще създадете отделена папка за вашия терариум и ще добавите първия си HTML файл. Ето два подхода, които можете да използвате:
**Опция 1: Използване на Visual Studio Code**
1. Отворете Visual Studio Code
2. Кликнете на "File" → "Open Folder" или използвайте `Ctrl+K, Ctrl+O` (Windows/Linux) или `Cmd+K, Cmd+O` (Mac)
3. Създайте нова папка, наречена `terrarium` и я изберете
4. В панела Explorer кликнете върху иконата "New File"
5. Назовете файла `index.html`
2. Щракнете "File" → "Open Folder" или използвайте `Ctrl+K, Ctrl+O` (Windows/Linux) или `Cmd+K, Cmd+O` (Mac)
3. Създайте нова папка на име`terrarium` и я изберете
4. В панела Explorer кликнете иконата за "New File"
5. Наименувайте файла си`index.html`


**Опция 2: Използване на команди в терминала**
```bash
@ -51,48 +96,73 @@ touch index.html
code index.html
```
**Ето какво постигат тези команди:**
- **Създават** нова директория, наречена`terrarium` за вашия проект
- **Навигират** в директорията на терариума
**Това, което тези команди правят:**
- **Създават** нова директорияс име`terrarium` за вашия проект
- **Навигират** до директорията terrarium
- **Създават** празен файл `index.html`
- **Отварят** файла във Visual Studio Code за редактиране
- **Отварят** файла за редактиране във Visual Studio Code
> 💡 **Полезен съвет**: Името на файла `index.html`е специално в уеб разработката. Когато някой посети уебсайт, браузърите автоматично търсят `index.html` като основна страница за показване. Това означава, че URL като `https://mysite.com/projects/` автоматично ще зареди файла `index.html` от папката `projects`, без да е необходимо да се посочва името на файла в URL.
> 💡 **Професионален съвет**: Името на файла `index.html`е специално в уеб разработката. Когато някой посети уебсайт, браузърите автоматично търсят `index.html` като начална страница за показване. Това означава, че URL като `https://mysite.com/projects/` автоматично ще сервира файла `index.html` от папката `projects` без да се налага да указвате името на файла в URL адреса.
## Разбиране на структурата на HTML документ
Всеки HTML документ следва специфична структура, която браузърите трябва да разбират и правилно да показват. Можете да си представите тази структура като официално писмо – то има задължителни елементи в определен ред, които помагат на получателя (в случая браузъра) да обработи съдържанието правилно.
Нека започнем, като добавим основата, която всеки HTML документ трябва да има.
Всеки HTML документ следва специфична структура, която браузърите трябва да разберат и показват правилно. Помислете за тази структура като за формално писмо – тя има задължителни елементи в определен ред, които помагат на получателя (в този случай браузъра) да обработи съдържанието правилно.
```mermaid
flowchart TD
A["<!DOCTYPE html>"] --> B["<html>"]
B --> C["<head>"]
C --> D["<title>"]
C --> E["<metacharset>"]
C --> F["<metaviewport>"]
B --> G["<body>"]
G --> H["<h1> Заглавие"]
G --> I["<div> Контейнери"]
G --> J["<img> Изображения"]
style A fill:#e1f5fe
style B fill:#f3e5f5
style C fill:#fff3e0
style G fill:#e8f5e8
```
Нека започнем с добавянето на съществената основа, от която всеки HTML документ се нуждае.
### Декларация DOCTYPE и коренов елемент
Първите два реда на всеки HTML файл служат като "въведение" на документа за браузъра:
Първите два реда от всеки HTML файл служат като „въведение“ на документа към браузъра:
```html
<!DOCTYPE html>
<html></html>
```
**Разбиране на това, което прави този код:**
- **Декларира** типа на документа като HTML5, използвайки `<!DOCTYPE html>`
- **Създава** кореновия елемент `<html>`, който ще съдържа цялото съдържание на страницата
- **Установява** съвременни уеб стандарти за правилно рендиране от браузъра
- **Осигурява** последователно показване на различни браузъри и устройства
**Разбиране какво прави този код:**
- **Декларира** типа на документа като HTML5 чрез`<!DOCTYPE html>`
- **Създава** кореновия `<html>` елемент, който ще съдържа цялото съдържание на страницата
- **Установява** съвременни уеб стандарти за правилно изобразяване от браузъра
- **Осигурява** последователно показване в различни браузъри и устройства
> 💡 **Съвет за VS Code**: Задръжте курсора върху всеки HTML таг във VS Code, за да видите полезна информация от MDN Web Docs, включително примери за употреба и подробности за съвместимостта с браузъри.
> 💡 **Съвет за VS Code**: Задръжте курсора над всеки HTML таг във VS Code, за да видите полезна информация от MDN Web Docs, включително примери за употреба и съвместимост с браузъри.
> 📚 **Научете повече**: Декларацията DOCTYPE предотвратява влизането на браузърите в "quirks mode", който се използваше за поддръжка на много стари уебсайтове. Съвременната уеб разработка използва простата декларация `<!DOCTYPE html>`, за да осигури [рендиране, съвместимо със стандартите](https://developer.mozilla.org/docs/Web/HTML/Quirks_Mode_and_Standards_Mode).
> 📚 **Научете повече**: Декларацията DOCTYPE предотвратява браузърите да влизат в „quirks mode“, който се използваше за поддръжка на много стари уебсайтове. Модерната уеб разработка използва опростената декларация `<!DOCTYPE html>`, за да осигури [изобразяване, съобразено със стандартите](https://developer.mozilla.org/docs/Web/HTML/Quirks_Mode_and_Standards_Mode).
## Добавяне на основни метаданни за документа
### 🔄 **Педагогическа проверка**
**Пауза и размисъл**: Уверете се, че разбирате:
- ✅ Защо всеки HTML документ се нуждае от DOCTYPE декларация
- ✅ Какво съдържа кореновият `<html>` елемент
- ✅ Как тази структура помага на браузърите да изобразят страниците правилно
Секцията `<head>` на HTML документа съдържа важна информация, която браузърите и търсачките се нуждаят, но която посетителите не виждат директно на страницата. Можете да я разглеждате като "задкулисна" информация, която помага на вашата уеб страница да работи правилно и да се показва коректно на различни устройства и платформи.
**Бърз тест**: Можете ли да обясните със свои думи какво означава „изобразяване, съобразено със стандартите“?
Тези метаданни казват на браузърите как да показват вашата страница, какво кодиране на символи да използват и как да се справят с различни размери на екрана – всичко това е от съществено значение за създаването на професионални, достъпни уеб страници.
## Добавяне на съществен метаинформация за документа
### Задача: Добавете секцията Head на документа
Секцията `<head>` в HTML документа съдържа важна информация, от която браузърите и търсачките се нуждаят, но която посетителите не виждат директно на страницата. Помислете за нея като „задкулисна“ информация, която помага на вашата уеб страница да работи правилно и да се показва коректно на различни устройства и платформи.
Вмъкнете тази секция `<head>` между вашите отварящи и затварящи тагове `<html>`:
Тази метаинформация казва на браузърите как да показват страницата ви, каква кодировка на символите да използват и как да се справят с различни размери на екрана – всички тези неща са важни за създаването на професионални и достъпни уеб страници.
### Задача: Добавете секцията head
Поставете този `<head>` раздел между отварящия и затварящия `<html>` тагове:
```html
<head>
@ -103,28 +173,28 @@ code index.html
</head>
```
**Разбивка на това, което постига всеки елемент:**
- **Задава** заглавието на страницата, което се появява в разделите на браузъра и резултатите от търсенето
- **Определя** UTF-8 кодиране на символи за правилно показване на текст по целия свят
- **Осигурява** съвместимост с модерните версии на Internet Explorer
- **Конфигурира** адаптивен дизайн, като задава изгледа да съответства на ширината на устройството
- **Контролира** началното ниво на мащабиране, за да показва съдържанието в естествен размер
**Разбор какво прави всеки елемент:**
- **Настройва** заглавието на страницата, което се появява в табовете на браузъра и в резултатите от търсене
- **Определя** UTF-8 кодиране за правилно изобразяване на текста по света
- **Гарантира** съвместимост с модерни версии на Internet Explorer
- **Конфигурира** отзивчив дизайн, като задава viewport със ширина, съответстваща на устройството
- **Контролира** началното ниво на мащабиране за показване на съдържанието в естествен размер
> 🤔 **Замислете се**: Какво би се случило, ако зададете мета таг за изглед като този: `<meta name="viewport" content="width=600">`? Това би принудило страницата винаги да бъде широка 600 пиксела, което би нарушило адаптивния дизайн! Научете повече за [правилната конфигурация на изгледа](https://developer.mozilla.org/docs/Web/HTML/Viewport_meta_tag).
> 🤔 **Помислете за това**: Какво би се случило, ако зададете viewport мета таг като този: `<meta name="viewport" content="width=600">`? Това ще принуди страницата да бъде винаги широка 600 пиксела, като ще развали отзивчивия дизайн! Научете повече за [правилната конфигурация на viewport](https://developer.mozilla.org/docs/Web/HTML/Viewport_meta_tag).
## Създаване на структурата на документа
## Изграждане на тялото на документа
Елементът `<body>` съдържа цялото видимо съдържание на вашата уеб страница – всичко, което потребителите ще видят и с което ще взаимодействат. Докато секцията `<head>`предоставя инструкции на браузъра, секцията `<body>` съдържа действителното съдържание: текст, изображения, бутони и други елементи, които създават вашия потребителски интерфейс.
Елементът `<body>` съдържа цялото видимо съдържание на вашата уеб страница – всичко, което потребителите ще видят и с което ще взаимодействат. Докато секцията `<head>`дава инструкции на браузъра, секцията `<body>` съдържа самото съдържание: текст, изображения, бутони и други елементи, които създават потребителския интерфейс.
Нека добавим структурата на тялото и да разберем как HTML таговете работят заедно, за да създадат смислено съдържание.
Нека добавим структурата на тялото и разберем как HTML таговете работят заедно, за да създадат смислено съдържание.
### Разбиране на структурата на HTML таговете
HTML използва двойки тагове за дефиниране на елементи. Повечето тагове имат отварящ таг като `<p>` и затварящ таг като `</p>`, със съдържание между тях: `<p>Hello, world!</p>`. Това създава елемент параграф, съдържащ текста "Hello, world!".
HTML използва тагове в двойки, за да дефинира елементи. Повечето тагове имат отварящ таг като `<p>` и затварящ таг като `</p>`, като съдържанието се поставя между тях: `<p>Hello, world!</p>`. Това създава параграфен елемент, съдържащ текста "Hello, world!".
### Задача: Добавете елемента Body
### Задача: Добавете body елемента
Актуализирайте вашия HTML файл, за да включите елемента `<body>`:
Обновете HTML файла си, за да включва елемента `<body>`:
```html
<!DOCTYPE html>
@ -139,104 +209,147 @@ HTML използва двойки тагове за дефиниране на
</html>
```
**Ето какво предоставя тази пълна структура:**
**Ето какво осигурява цялата тази структура:**
- **Установява** основната рамка на HTML5 документа
- **Включва** основни метаданни за правилно рендиране от браузъра
- **Създава** празно тяло, готово за вашето видимо съдържание
- **Следва** най-добрите практики за съвременнауеб разработка
- **Включва** съществена метаинформация за правилно изобразяване от браузъра
- **Създава** празно тяло, готово за видимото ви съдържание
- **Следва** най-добрите практики в модернатауеб разработка
Сега сте готови да добавите видимите елементи на вашия терариум. Ще използваме елементи `<div>` като контейнери за организиране на различни секции от съдържанието и елементи `<img>` за показване на изображенията на растенията.
Сега сте готови да добавите видимите елементи на вашия терариум. Ще използваме `<div>` елементи като контейнери за организиране на различни секции с съдържание и `<img>` елементи за показване на изображенията на растения.
### Работа с изображения и контейнери за оформление
Изображенията са специални в HTML, защото използват "самозатварящи се" тагове. За разлика от елементи като `<p></p>`, които обгръщат съдържание, тагът `<img>` съдържа цялата необходима информация в самия таг, използвайки атрибути като `src` за пътя на файла с изображението и `alt` за достъпност.
Изображенията са специални в HTML, защото използват „самозатварящи“ тагове. За разлика от елементи като `<p></p>`, които заобикалят съдържание, тагът `<img>` съдържа цялата необходима информация в себе си чрез атрибути като `src` за пътя към изображението и `alt` за достъпност.
Преди да добавите изображения към вашия HTML, ще трябва правилно да организирате файловете на проекта, като създадете папка за изображения и добавите графиките на растенията.
Преди да добавите изображения в HTML, ще трябва да организирате файловете на проекта си правилно, като създадете папка за изображения и добавите графиките на растенията.
**Първо, настройте вашите изображения:**
1. Създайте папка, наречена `images` вътре в папката на вашия проект за терариум
2. Изтеглете изображенията на растенията от [папката с решения](../../../../3-terrarium/solution/images) (общо 14 изображения на растения)
1. Създайте папка на име `images` в папката на вашия терариум проект
2. Изтеглете изображенията на растенията от [папката с решение](../../../../3-terrarium/solution/images) (общо 14 изображения на растения)
3. Копирайте всички изображения на растения в новата си папка `images`
### Задача: Създайте оформление за показване на растенията
Сега добавете изображенията на растенията, организирани в две колони между вашите тагове `<body></body>`:
Сега добавете изображенията на растения, организирани в две колони между вашите тагове `<body></body>`:
**Стъпка по стъпка, ето каквосе случва в този код:**
- **Създава** основен контейнер на страницата с`id="page"`, който да държи цялото съдържание
**Стъпка по стъпка, товасе случва в този код:**
- **Създава** главен контейнер на страницата с`id="page"`, който държи цялото съдържание
- **Установява** два контейнера за колони: `left-container` и `right-container`
- **Организира** 7 растения в лявата колона и 7 растения в дясната колона
- **Обгръща** всяко изображение на растение в `plant-holder` div за индивидуално позициониране
- **Прилага** последователни имена на класове за стилизиране с CSS в следващия урок
- **Присвоява** уникални ID-та на всяко изображение на растение за бъдеща интерактивностс JavaScript
- **Обгражда** всяко изображение на растение в `plant-holder` div за индивидуално позициониране
- **Прилага** последователни имена на класове за стилове в следващия урок
- **Задава** уникални ID-та на всяко изображение за по-късна интеракцияс JavaScript
- **Включва** правилни пътища към папката с изображения
> 🤔 **Замислете се**: Забележете, че всички изображения в момента имат еднакъв alt текст "plant". Това не е идеално за достъпност. Потребителите на екранни четци ще чуят "plant" повторено 14 пъти, без да знаят кое конкретно растение показва всяко изображение. Можете ли да измислите по-добър, по-описателен alt текст за всяко изображение?
> 🤔 **Помислете за това**: Обърнете внимание, че всички изображения в момента имат еднакъв alt текст „plant“. Това не е идеално за достъпност. Потребителите на екранни четци биха чули „plant“ повторено 14 пъти, без да знаят кое точно растение е всяко изображение. Можете ли да измислите по-добри, по-описателни alt текстове за всяко изображение?
> 📝 **Типове HTML елементи**: Елементите `<div>`са"блокови" и заемат цялата ширина, докато елементите `<span>`са"вградени" и заемат само необходимата ширина. Какво мислите, че би се случило, ако замените всички тези тагове `<div>`с тагове `<span>`?
> 📝 **Типове HTML елементи**: Елементите `<div>`са„блокови“ и заемат цялата ширина, докато елементите `<span>`са„инлайн“ и заемат само необходимата ширина. Какво мислите какво би станало, ако замените всички тези `<div>` тагове с`<span>` тагове?
С добавянето на този маркъп, растенията ще се появят на екрана, въпреки че все още няма да изглеждат добре – за това ще се погрижи CSS в следващия урок! Засега имате солидна HTML основа, която правилно организира вашето съдържание и следва най-добрите практики за достъпност.
### 🔄 **Педагогическа проверка**
**Разбиране на структурата**: Отделете момент, за да прегледате структурите в HTML:
- ✅ Можете ли да откриете главните контейнери в оформлението си?
- ✅ Разбирате ли защо всяко изображение има уникално ID?
- ✅ Как бихте описали предназначението на `plant-holder` div-овете?
## Използване на семантичен HTML за достъпност
**Визуална проверка**: Отворете своя HTML файл в браузър. Трябва да видите:
- Основен списък с изображения на растения
- Изображенията организирани в две колони
- Просто, нестилизирано оформление
**Запомнете**: Този обикновен вид е точно това, което HTML трябва да изглежда преди стилизиране с CSS!
Семантичният HTML означава избор на HTML елементи въз основа на тяхното значение и цел, а не само на външния им вид. Когато използвате семантичен маркъп, вие комуникирате структурата и значението на вашето съдържание към браузъри, търсачки и помощни технологии като екранни четци.
С добавения този маркъп растенията ще се покажат на екрана, макар и все още да не изглеждат полиран – за това е CSS в следващия урок! За момента имате солидна HTML основа, която правилно организира съдържанието и следва най-добрите практики за достъпност.
Този подход прави вашите уебсайтове по-достъпни за потребители с увреждания и помага на търсачките да разбират по-добре вашето съдържание. Това е основен принцип на съвременната уеб разработка, който създава по-добри преживявания за всички.
## Използване на семантичен HTML за достъпност
Семантичният HTML означава да избирате HTML елементи според тяхното значение и цел, а не само според въздействието им върху визията. Когато използвате семантичен маркъп, вие комуникирате структурата и значението на съдържанието си към браузъри, търсачки и помощни технологии като екранни четци.
```mermaid
flowchart TD
A[Трябва ли да добавите съдържание?] --> B{Какъв тип?}
B -->|Главен заглавен ред| C["<h1>"]
B -->|Подзаглавие| D["<h2>, <h3>, и т.н."]
B -->|Параграф| E["<p>"]
B -->|Списък| F["<ul>, <ol>"]
B -->|Навигация| G["<nav>"]
B -->|Статия| H["<article>"]
B -->|Секция| I["<section>"]
B -->|Общ контейнер| J["<div>"]
C --> K[Четещите на екрана обявяват като главен заглавен ред]
D --> L[Създава правилна йерархия на заглавията]
E --> M[Осигурява правилно разстояние на текста]
F --> N[Активира навигационни преки пътища за списъци]
G --> O[Идентифицира навигационни ориентири]
H --> P[Маркира самостоятелно съдържание]
I --> Q[Групира свързано съдържание]
J --> R[Използвайте само когато няма подходящ семантичен таг]
style C fill:#4caf50
style D fill:#4caf50
style E fill:#4caf50
style F fill:#4caf50
style G fill:#2196f3
style H fill:#2196f3
style I fill:#2196f3
style J fill:#ff9800
```
Този подход прави вашите уебсайтове по-достъпни за потребители с увреждания и помага на търсачките по-добре да разбират съдържанието ви. Това е фундаментален принцип на модерната уеб разработка, който създава по-добри изживявания за всички.
### Добавяне на семантично заглавие на страницата
Нека добавим подходящо заглавие към вашата страница за терариум. Вмъкнете този ред точно след вашия отварящ `<body>` таг:
Нека добавим подходящо заглавие на страницата на вашия терариум. Поставете този ред веднага след отварящия`<body>` таг:
```html
<h1>My Terrarium</h1>
@ -245,30 +358,30 @@ HTML използва двойки тагове за дефиниране на
**Защо семантичният маркъп е важен:**
- **Помага** на екранните четци да навигират и разбират структурата на страницата
- **Подобрява** оптимизацията за търсачки (SEO), като изяснява йерархията на съдържанието
- **Подобрява** достъпността за потребители с зрителни увреждания или когнитивни различия
- **Създава** по-добри потребителски преживявания на всички устройства и платформи
- **Следва** уеб стандартите и най-добрите практики за професионална разработка
- **Подсилва** достъпността за потребители с нарушения на зрението или когнитивни различия
- **Създава** по-добри потребителски изживявания на всички устройства и платформи
- **Следва** уеб стандартите и добрите практики за професионална разработка
**Примери за семантични срещу несемантични избори:**
| Съдържание на статия | `<article><p></p></article>` | `<div class="content"><div></div></div>` |
> 🎥 **Вижте го в действие**: Гледайте [как екранните четци взаимодействат суеб страници](https://www.youtube.com/watch?v=OUDV1gqs9GA), за да разберете защо семантичният маркъп еот решаващо значение за достъпността. Забележете как правилната HTML структура помага на потребителите да навигират ефективно.
> 🎥 **Вижте го в действие**: Гледайте [как екранните четци взаимодействат суеб страници](https://www.youtube.com/watch?v=OUDV1gqs9GA), за да разберете защо семантичният маркъп е решаващ за достъпността. Забележете как правилната HTML структура помага на потребителите да навигират ефективно.
## Създаване на контейнера за терариума
## Създаване на контейнер за терариума
Сега нека добавим HTML структурата за самия терариум – стъкления контейнер, в който растенията ще бъдат поставени. Тази секция демонстрира важна концепция: HTML предоставя структура, но без стилизиране с CSS, тези елементи все още няма да бъдат видими.
Сега нека добавим HTML структурата за самия терариум – стъкления контейнер, където растенията в крайна сметка ще бъдат поставени. Тази секция демонстрира важна концепция: HTML осигурява структура, но без CSS стилове тези елементи все още няма да се виждат.
Маркупът за терариума използва описателни имена на класове, които ще направят стилизирането с CSS интуитивно и лесно за поддръжка в следващия урок.
Маркъпът за терариума използва описателни имена на класове, които ще направят стиловете с CSS интуитивни и лесни за поддръжка в следващия урок.
### Задача: Добавете структурата на терариума
Вмъкнете този маркуп над последния `</div>` таг (преди затварящия таг на контейнера на страницата):
Поставете този маркъп над последния таг `</div>` (преди затварящия таг на контейнера на страницата):
```html
<divid="terrarium">
@ -282,71 +395,200 @@ HTML използва двойки тагове за дефиниране на
</div>
```
**Разбиране на тази структура на терариума:**
- **Създава** основен контейнер за терариума с уникален ID за стилизиране
- **Определя** отделни елементи за всеки визуален компонент (горна част, стени, пръст,
**Подканва:** Създайте семантичен HTML раздел, който включва основно заглавие "Ръководство за грижа за растенията", три подраздела със заглавия "Поливане", "Изисквания за светлина" и "Грижа за почвата", като всеки съдържа параграф с информация за грижата за растенията. Използвайте подходящи семантични HTML тагове като `<section>`, `<h2>`, `<h3>` и `<p>`, за да структурирате съдържанието правилно.
Научете повече за [режим агент](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
## Предизвикателство: История на HTML
**Научете за еволюцията на уеб**
HTML сее развил значително, откакто Тим Бърнърс-Лий създаде първия уеб браузър в CERN през 1990 г. Някои по-стари тагове като `<marquee>` вече са остарели, защото не работят добре с модерните стандарти за достъпност и принципите на адаптивния дизайн.
**Опитайте този експеримент:**
1. Временно обгърнете заглавието си `<h1>` в таг `<marquee>`: `<marquee><h1>Моят терариум</h1></marquee>`
2. Отворете страницата си в браузър и наблюдавайте ефекта на скролиране
3. Помислете защо този таг е остарял (подсказка: помислете за потребителското изживяване и достъпността)
4. Премахнете тага `<marquee>` и се върнете към семантичната маркировка
**Въпроси за размисъл:**
- Как скролиращото заглавие може да повлияе на потребители с зрителни увреждания или чувствителност към движение?
- Какви съвременни CSS техники могат да постигнат подобни визуални ефекти по-достъпно?
- Защо е важно да се използват актуални уеб стандарти вместо остарели елементи?
Научете повече за [остарели и премахнати HTML елементи](https://developer.mozilla.org/docs/Web/HTML/Element#Obsolete_and_deprecated_elements), за да разберете как уеб стандартите се развиват за подобряване на потребителското изживяване.
## Тест след лекцията
[Тест след лекцията](https://ff-quizzes.netlify.app/web/quiz/16)
## Преглед и самостоятелно обучение
**Задълбочете знанията си за HTML**
HTML е основата на уеб вече повече от 30 години, развивайки се от прост език за маркиране на документи до сложна платформа за създаване на интерактивни приложения. Разбирането на тази еволюция ви помага да оцените съвременните уеб стандарти и да вземате по-добри решения за разработка.
**Препоръчителни пътища за обучение:**
1. **История и еволюция на HTML**
- Проучете хронологията от HTML 1.0 до HTML5
- Разгледайте защо определени тагове са премахнати (достъпност, удобство за мобилни устройства, поддръжка)
- Изследвайте нововъзникващи HTML функции и предложения
2. **Дълбоко разбиране на семантичния HTML**
- Изучете пълния списък на [семантични елементи в HTML5](https://developer.mozilla.org/docs/Web/HTML/Element)
- Практикувайте идентифицирането кога да използвате `<article>`, `<section>`, `<aside>` и `<main>`
- Научете за ARIA атрибути за подобрена достъпност
3. **Съвременно уеб разработване**
- Разгледайте [създаване на адаптивни уебсайтове](https://docs.microsoft.com/learn/modules/build-simple-website/?WT.mc_id=academic-77807-sagibbon) на Microsoft Learn
- Разберете как HTML се интегрира с CSS и JavaScript
- Научете за най-добрите практики за уеб производителност и SEO
**Въпроси за размисъл:**
- Кои остарели HTML тагове открихте и защо са премахнати?
- Какви нови HTML функции се предлагат за бъдещи версии?
- Как семантичният HTML допринася за уеб достъпността и SEO?
**Разбиране на тази структура за терариума:**
- **Създава** главен контейнер на терариума с уникално ID за стилизиране
- **Дефинира** отделни елементи за всеки визуален компонент (горна част, стени, пръст, долна част)
- **Включва** вложени елементи за ефекти на отражение на стъкло (лъскави елементи)
- **Използва** описателни имена на класове, които ясно показват целта на всеки елемент
- **Подготвя** структурата за CSS стилизиране, което ще създаде външния вид на стъклен терариум
> 🤔 **Забелязвате ли нещо?**: Въпреки че добавихте този маркъп, не виждате нищо ново на страницата! Това прекрасно илюстрира как HTML осигурява структура, а CSS — визия. Тези `<div>` елементи съществуват, но все още нямат визуално стилизиране – то предстои в следващия урок!
## Задача
```mermaid
flowchart TD
A[HTML Документ] --> B[Главна Част]
A --> C[Основно Съдържание]
B --> D[Елемент Заглавие]
B --> E[Мета Charset]
B --> F[Мета Viewport]
C --> G[Основен Заглавен Текст]
C --> H[Контейнер на Страницата]
H --> I[Ляв Контейнер с 7 растения]
H --> J[Десен Контейнер с 7 растения]
H --> K[Структура на Терариума]
style A fill:#e1f5fe
style B fill:#fff3e0
style C fill:#e8f5e8
style H fill:#f3e5f5
```
### 🔄 **Педагогическа проверка**
**Владеене на HTML структурата**: Преди да продължите, уверете се, че можете:
- ✅ Да обясните разликата между HTML структура и визуален вид
- ✅ Да различите семантични и несемантични HTML елементи
- ✅ Да опишете как правилният маркъп подпомага достъпността
- ✅ Да разпознаете пълната дървовидна структура на документа
**Тествайте разбирането си**: Опитайте да отворите вашия HTML файл в браузър с изключен JavaScript и без CSS. Това ще ви покаже чистата семантична структура, която сте създали!
---
## Предизвикателство с GitHub Copilot Agent
Използвайте режим Agent, за да изпълните следното предизвикателство:
**Описание:** Създайте семантична HTML структура за секция с указания за грижа за растенията, която може да бъде добавена към проекта за терариум.
**Подсказка:** Създайте семантична HTML секция, която включва главен заглавен елемент "Указания за грижа за растенията", три подтемички с заглавия "Поливане", "Изисквания към светлината" и "Грижа за почвата", всяка съдържаща параграф с информация за грижите. Използвайте подходящи семантични HTML тагове като `<section>`, `<h2>`, `<h3>` и `<p>`, за да структурирате съдържанието адекватно.
Научете повече за [режим agent](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
## Предизвикателство за изследване на историята на HTML
**Научаване за еволюцията на уеб**
HTML еволюира значително откакто Тим Бърнърс-Лий създава първия уеб браузър в CERN през 1990 г. Някои по-стари тагове като `<marquee>` вече са остарели, тъй като не се съчетават добре с модерните стандарти за достъпност и принципите на адаптивен дизайн.
**Опитайте този експеримент:**
1. Временно обгърнете вашето `<h1>` заглавие с`<marquee>` тага: `<marquee><h1>Моят терариум</h1></marquee>`
2. Отворете страницата в браузър и наблюдавайте ефекта на превъртане
3. Помислете защо този тага е остарял (подсказка: за удобство на потребителя и достъпност)
4. Премахнете `<marquee>` тага и се върнете към семантичен маркъп
**Въпроси за размисъл:**
- Как превъртащо се заглавие може да повлияе на потребители с нарушения на зрението или чувствителност към движение?
- Какви съвременни CSS техники биха могли да постигнат подобни визуални ефекти по-достъпно?
- Защо е важно да се използват актуални уеб стандарти вместо остарели елементи?
Разгледайте повече за [остарели и отхвърлени HTML елементи](https://developer.mozilla.org/docs/Web/HTML/Element#Obsolete_and_deprecated_elements), за да разберете как уеб стандартите се развиват, за да подобрят потребителското изживяване.
## Тест след лекцията
[Тест след лекцията](https://ff-quizzes.netlify.app/web/quiz/16)
## Преглед и самообучение
**Удължете знанията си по HTML**
HTML е основата на уеб технологиите повече от 30 години, развил се от прост език за маркиране на документи до сложна платформа за създаване на интерактивни приложения. Разбирането на тази еволюция ви помага да оцените съвременните уеб стандарти и да вземате по-добри решения при разработката.
**Препоръчани учебни пътеки:**
1. **История и еволюция на HTML**
- Изследвайте хронологията от HTML 1.0 до HTML5
- Разберете защо някои тагове са отхвърлени (достъпност, удобство за мобилни устройства, поддръжка)
- Проучете нови функции и предложения за HTML
2. **Дълбоко навлизане в семантичен HTML**
- Проучете пълния списък със [семантични HTML5 елементи](https://developer.mozilla.org/docs/Web/HTML/Element)
- Практикувайте кога да използвате `<article>`, `<section>`, `<aside>` и `<main>`
- Запознайте сес ARIA атрибути за подобрена достъпност
3. **Модерен уеб дизайн и разработка**
- Изследвайте [създаването на адаптивни уебсайтове](https://docs.microsoft.com/learn/modules/build-simple-website/?WT.mc_id=academic-77807-sagibbon) в Microsoft Learn
- Разберете как HTML се интегрира с CSS и JavaScript
- Научете за уеб оптимизация и SEO най-добри практики
**Въпроси за размисъл:**
- Кои остарели HTML тагове открихте и защо са премахнати?
- Какви нови HTML функции се предлагат за бъдещи версии?
- Как семантичният HTML допринася за уеб достъпност и SEO?
### ⚡ **Какво можете да направите през следващите 5 минути**
- [ ] Отворете DevTools (F12) и инспектирайте HTML структурата на любимия си уебсайт
- [ ] Създайте прост HTML файл с основни тагове: `<h1>`, `<p>`, и `<img>`
- [ ] Валидирайте HTML кода си с онлайн валидатор на W3C
- [ ] Опитайте да добавите коментар към HTML с`<!-- comment -->`
### 🎯 **Какво може да постигнете през този час**
- [ ] Завършете теста след урока и прегледайте концепциите за семантичен HTML
- [ ] Изградете проста уебстраница за себе си с правилна HTML структура
- [ ] Експериментирайте с различни нива на заглавия и тагове за форматиране на текст
- [ ] Добавете изображения и връзки, за да практикувате интеграция на мултимедия
- [ ] Изследвайте HTML5 функции, които още не сте пробвали
### 📅 **Вашето седмично HTML пътуване**
- [ ] Завършете проекта терариум със семантичен маркъп
- [ ] Създайте достъпна уебстраница с ARIA етикети и роли
- [ ] Практикувайте създаване на форми с различни типове полета
- [ ] Разгледайте HTML5 APIs като localStorage или геолокация
- [ ] Изучавайте адаптивни HTML шаблони и мобилно ориентиран дизайн
- [ ] Преглеждайте HTML код на други разработчици за най-добри практики
### 🌟 **Вашата месечна основа за уеб развитие**
- [ ] Изградете портфолио уебсайт, показващ уменията ви в HTML
- [ ] Научете шаблониране в HTML с рамка като Handlebars
- [ ] Допринасяйте към open source проекти чрез подобряване на HTML документация
- [ ] Владеете напреднали HTML концепции като персонализирани елементи
- [ ] Интегрирайте HTML с CSS фреймуъркове и JavaScript библиотеки
- [ ] Наставлявайте други в основите на HTML
## 🎯 Вашият времеви план за овладяване на HTML
```mermaid
timeline
title Прогрес в изучаването на HTML
section Основи (5 минути)
Структура на документа: DOCTYPE декларация
: Коренен елемент HTML
: Разбиране на Head и Body
section Метаданни (10 минути)
Основни мета тагове: Кодиране на символи
: Конфигурация на изгледа (viewport)
: Съвместимост с браузъри
section Създаване на съдържание (15 минути)
Интегриране на изображения: Правилни пътища към файлове
: Значението на алтернативния текст
: Самозатварящи се тагове
section Организация на оформлението (20 минути)
Стратегия за контейнери: Div елементи за структура
: Именуване на класове и ID-та
: Вложена йерархия на елементите
section Семантично майсторство (30 минути)
Смислени маркъпи: Йерархия на заглавията
: Навигация с четци за екран
: Най-добри практики за достъпност
section Разширени концепции (1 час)
Функции на HTML5: Модерни семантични елементи
: ARIA атрибути
: Съображения за производителност
section Професионални умения (1 седмица)
Организация на кода: Модели на структурата на файловете
: Поддържащ маркъп
: Екипно сътрудничество
section Ниво експерт (1 месец)
Модерни уеб стандарти: Прогресивно подобрение
: Съвместимост между браузъри
: Актуализации на спецификацията на HTML
```
### 🛠️ Резюме на вашия HTML инструментариум
След завършването на този урок вече имате:
- **Структура на документа**: Пълна основа HTML5 с правилен DOCTYPE
- **Семантичен маркъп**: Смислени тагове, които повишават достъпността и SEO
- **Интеграция на изображения**: Добра организация на файловете и практики за alt текст
- **Контейнери за оформление**: Стратегическо използване на div с описателни класове
- **Осъзнаване за достъпността**: Познаване на навигацията с четец на екран
- **Модерни стандарти**: Настоящи практики в HTML5 и познаване на остарели тагове
- **Основи за проекта**: Солидна база за CSS стилизиране и JavaScript интерактивност
**Следващи стъпки**: Вашата HTML структура е готова за CSS стилизиране! Семантичната основа, която сте изградили, ще направи следващия урок много по-лесен за разбиране.
## Задача
[Практикувайте HTML: Създайте макет на блог](assignment.md)
---
**Отказ от отговорност**:
Този документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Отказ от отговорност**:
Този документ е преведен с помощта на AI преводаческа услуга [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля имайте предвид, че автоматизираните преводи могат да съдържат грешки или неточности. Оригиналният документ на неговия език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за всякакви недоразумения или неправилни тълкувания, произтичащи от използването на този превод.

> Скица от [Tomomi Imura](https://twitter.com/girlie_mac)
Спомняте ли си как вашият HTML терариум изглеждаше доста обикновен? С CSS можем да преобразим тази проста структура в нещо визуално привлекателно.
Ако HTML е като изграждането на рамката на къща, то CSS е всичко, което я прави уютен дом - цветовете на стените, подредбата на мебелите, осветлението и как стаите се свързват помежду си. Помислете как дворецът Версай е започнал като обикновена ловна хижа, но внимателното внимание към декорацията и оформлението гое превърнало в една от най-великолепните сгради в света.
Днес ще преобразим вашия терариум от функционален в изискан. Ще научите как да позиционирате елементи прецизно, да създавате оформления, които се адаптират към различни размери на екрана, и да създавате визуална привлекателност, която прави уебсайтовете ангажиращи.
До края на този урок ще видите как стратегическото стилизиране с CSS може драматично да подобри вашия проект. Нека добавим стил към вашия терариум.
## Предварителен тест
# Terrarium Project Част 2: Въведение в CSS
```mermaid
journey
title Вашето CSS стилово пътешествие
section Основи
Връзване на CSS файл: 3: Student
Разбиране на каскада: 4: Student
Научаване на унаследяване: 4: Student
section Селектори
Целево насочване на елементи: 4: Student
Шаблони на класове: 5: Student
Специфичност на ID: 5: Student
section Оформление
Позициониране на елементи: 4: Student
Създаване на контейнери: 5: Student
Сглобяване на терариум: 5: Student
section Финализиране
Добавяне на визуални ефекти: 5: Student
Адаптивен дизайн: 5: Student
Стъклени отражения: 5: Student
```

> Скетчноут от [Tomomi Imura](https://twitter.com/girlie_mac)
Спомняте ли си как вашият HTML терариум изглеждаше доста основен? CSS е мястото, където преобразяваме тази обикновена структура във визуално привлекателна.
Ако HTML е като построяването на рамката на къща, тогава CSS е всичко, което я кара да се чувства като дом - цветовете на боята, подредбата на мебелите, осветлението и как стаите се свързват една с друга. Помислете как Дворецът във Версай е започнал като проста ловна хижа, но внимателното внимание към украсата и подредбата го превърна в една от най-величествените сгради в света.
Днес ще преобразим вашия терариум от функционален в изискан. Ще научите как точно да позиционирате елементите, да направите оформленията адаптивни към различни размери на екрана и да създадете визуалната привлекателност, която прави уебсайтовете ангажиращи.
Към края на този урок ще видите как стратегическото стилизиране с CSS може драматично да подобри вашия проект. Нека добавим стил към вашия терариум.
CSS често се възприема като инструмент за "разкрасяване", но всъщност има много по-широка цел. CSS е като режисьор на филм - контролирате не само как всичко изглежда, но и как се движи, реагира на взаимодействие и се адаптира към различни ситуации.
Често CSS се възприема само като „правене на нещата красиви“, но той служи на много по-широка цел. CSS е като режисьор на филм – вие контролирате не само как изглежда всичко, но и как се движи, реагира на взаимодействия и се адаптира към различни ситуации.
Съвременният CSS е изключително способен. Можете да пишете код, който автоматично настройва оформленията за телефони, таблети и настолни компютри. Можете да създавате плавни анимации, които насочват вниманието на потребителите към важни елементи. Резултатите могат да бъдат доста впечатляващи, когато всичко работи заедно.
Модерният CSS е изключително способен. Можете да пишете код, който автоматично адаптира оформленията за телефони, таблети и настолни компютри. Можете да създавате плавни анимации, които насочват вниманието на потребителите там, където е нужно. Резултатите могат да бъдат доста впечатляващи, когато всичко работи заедно.
> 💡 **Съвет**: CSS постоянно се развива с нови функции и възможности. Винаги проверявайте [CanIUse.com](https://caniuse.com), за да се уверите, че браузърите поддържат новите функции на CSS, преди да ги използвате в производствени проекти.
> 💡 **Профи съвет**: CSS постоянно се развива с нови функции и възможности. Винаги проверявайте [CanIUse.com](https://caniuse.com), за да потвърдите поддръжката в браузърите за новите CSS функции, преди да ги използвате в продукционни проекти.
**Ето какво ще постигнем в този урок:**
- **Създаване** на цялостен визуален дизайн за вашия терариум с помощта на съвременни техники на CSS
- **Изследване** на основни концепции като каскада, наследяване и селектори в CSS
- **Прилагане** на стратегии за позициониране и оформление, които се адаптират към различни устройства
- **Изграждане** на контейнер за терариума с помощта на форми и стилизиране в CSS
- **Създаване** на пълен визуален дизайн за вашия терариум, използвайки модерни CSS техники
- **Изследване** на основни концепции като каскада, наследяване и CSS селектори
- **Прилагане** на адаптивни стратегии за позициониране и оформление
- **Изграждане** на контейнера на терариума чрез CSS форми и стилизиране
### Предпоставки
### Предварителни изисквания
Трябва да сте завършили HTML структурата за вашия терариум от предишния урок и да сте готови да я стилизирате.
Трябва да сте създали HTML структурата за вашия терариум от предишния урок и да я имате готова за стилизиране.
> 📺 **Видео ресурс**: Вижте този полезен видео урок
>
> [](https://www.youtube.com/watch?v=6yIdOIV9p1I)
> 📺 **Видео ресурс**: Вижте този полезен видео урок
>
> [](https://www.youtube.com/watch?v=6yIdOIV9p1I)
### Настройка на вашия CSS файл
### Настройване на вашия CSS файл
Преди да започнем със стилизирането, трябва да свържем CSS с нашия HTML. Тази връзка казва на браузъра къде да намери инструкциите за стилизиране на нашия терариум.
В папката на вашия терариум създайте нов файл, наречен `style.css`, след това го свържете в секцията `<head>` на вашия HTML документ:
В папката на вашия терариум създайте нов файл на име `style.css`, след коетого свържете в секцията `<head>` на вашия HTML документ:
```html
<linkrel="stylesheet"href="./style.css"/>
```
**Ето какво прави този код:**
**Какво прави този код:**
- **Създава** връзка между вашите HTML и CSS файлове
- **Указва** на браузъра да зареди и приложи стиловете от `style.css`
- **Използва** атрибута `rel="stylesheet"`, за да посочи, че това е CSS файл
- **Реферира** пътя към файла с`href="./style.css"`
- **Казва** на браузъра да зареди и приложи стиловете от `style.css`
- **Използва** атрибута `rel="stylesheet"`, който указва, че това е CSS файл
- **Реферира** файлa пътс`href="./style.css"`
## Разбиране на каскадата в CSS
## Разбиране на CSS каскадата
Чудили ли сте се защо CSS се нарича "каскадни" стилове? Стиловете се спускат като водопад и понякога се конфликтират помежду си.
Някога чудили ли сте се защо CSS се нарича „Cascading“ Style Sheets (Каскадни стилове)? Стиловете се спускат като водопад и понякога си противоречат.
Помислете как работят военните командни структури - генерална заповед може да гласи "всички войници да носят зелено", но специфична заповед за вашето подразделение може да гласи "носете официални униформи за церемонията". По-специфичната инструкция има предимство. CSS следва подобна логика и разбирането на тази йерархия прави отстраняването на грешки много по-лесно.
Помислете как работят военните командни структури – генералска заповед може да казва „всички войски да носят зелено“, но конкретна заповед към вашия отряд може да казва „за церемонията носете официален син“. По-конкретната инструкция има предимство. CSS следва подобна логика и разбирането на тази иерархия прави отстраняването на грешки много по-лесно.
### Експериментиране с приоритетите на каскадата
### Експериментиране с приоритета на каскадата
Нека видим каскадата в действие, като създадем конфликт в стиловете. Първо, добавете вътрешен стил към вашия `<h1>` таг:
Нека видим каскадата в действие, като създадем стилов конфликт. Първо, добавете инлайн стил към вашия `<h1>` таг:
```html
<h1style="color: red">My Terrarium</h1>
```
**Какво прави този код:**
- **Прилага** червен цвят директно към елемента `<h1>`с помощта на вътрешен стил
- **Прилага** червен цвят директно на елемента `<h1>` чрез инлайн стил
- **Използва** атрибута `style`, за да вгради CSS директно в HTML
- **Създава** правило за стилс най-висок приоритет за този конкретен елемент
- **Създава** стилово правилос най-висок приоритет за този конкретен елемент
След това добавете това правило към вашия файл `style.css`:
След това добавете това правило във вашия файл `style.css`:
```css
h1 {
@ -89,27 +143,48 @@ h1 {
}
```
**В горното сме:**
- **Дефинирали** правило в CSS, което таргетира всички елементи `<h1>`
- **Задавали** текстов цвят син чрез външен стилов файл
- **Създавали** правило с по-нисък приоритет в сравнение с вътрешните стилове
✅ **Проверка на знанията**: Кой цвят се показва във вашето уеб приложение? Защо този цвят има предимство? Можете ли да си представите сценарии, в които бихте искали да замените стиловете?
> 💡 **Ред на приоритетите в CSS (от най-висок към най-нисък):**
> 1. **Вътрешни стилове** (атрибут style)
> 2. **ID-та** (#myId)
> 3. **Класове** (.myClass) и атрибути
> 4. **Селектори на елементи** (h1, div, p)
> 5. **По подразбиране на браузъра**
**В горния случай сме:**
- **Дефинирали** CSS правило, което таргетира всички `<h1>` елементи
- **Зададени** синия цвят на текста чрез външен стилов файл
- **Създадено** правило с по-нисък приоритет в сравнение с инлайн стиловете
✅ **Проверка на знанията**: Кой цвят се показва във вашето уеб приложение? Защо този цвят печели? Можете ли да измислите ситуации, когато бихте искали да презапишете стилове?
```mermaid
flowchart TD
A["Браузърът среща елемент h1"] --> B{"Провери за стилове на линия"}
B -->|Намерени| C["style='color: red'"]
B -->|Няма| D{"Провери за правила с ID"}
C --> E["Приложи червен цвят (1000 точки)"]
D -->|Намерени| F["#heading { color: green }"]
D -->|Няма| G{"Провери за правила с клас"}
F --> H["Приложи зелен цвят (100 точки)"]
G -->|Намерени| I[".title { color: blue }"]
G -->|Няма| J{"Провери за правила за елементи"}
I --> K["Приложи син цвят (10 точки)"]
J -->|Намерени| L["h1 { color: purple }"]
J -->|Няма| M["Използвай браузър по подразбиране"]
L --> N["Приложи лилав цвят (1 точка)"]
style C fill:#ff6b6b
style F fill:#51cf66
style I fill:#339af0
style L fill:#9775fa
```
> 💡 **Ред на приоритет в CSS (от най-висок към най-нисък):**
> 1. **Инлайн стилове** (атрибут style)
> 2. **ID-та** (#myId)
> 3. **Класове** (.myClass) и атрибути
> 4. **Селектори на елементи** (h1, div, p)
> 5. **Браузърни стойности по подразбиране**
## CSS наследяване в действие
CSS наследяването работи като генетика - елементите наследяват определени свойства от своите родителски елементи. Ако зададете шрифт на елемента body, целият текст вътре автоматично използва същия шрифт. Това е подобно на начина, по който характерната челюст на фамилията Хабсбургсе появява през поколенията, без да се задава за всеки индивид.
CSS наследяването работи като генетиката – елементите наследяват определени свойства от родителските елементи. Ако зададете шрифт на `body`, целият текст вътре автоматично използва същия шрифт. Това е подобно на това как отличителната челюст на Хабсбургското семейство се явява в поколения, без да е специфично посочено за всеки отделен.
Въпреки това, не всичко се наследява. Стилове на текст като шрифтове и цветове се наследяват, но свойства на оформлението като отстъпи и рамки не се наследяват. Точно както децата могат да наследят физически черти, но не и модните предпочитания на родителите си.
Обаче, не всичко се наследява. Текстови стилове като шрифтове и цветове се наследяват, но свойства на оформление като отстояния (margins) и рамки не се наследяват. Подобно на това, че децата могат да наследят физически черти, но не и модните предпочитания на родителите си.
### Наблюдение на наследяването на шрифта
### Наблюдаване на наследяването на шрифтове
Нека видим наследяването в действие, като зададем шрифт на елемента `<body>`:
@ -119,31 +194,46 @@ body {
}
```
**Разбивка на случващото се тук:**
- **Задава** шрифт за целия страница, таргетирайки елемента `<body>`
- **Използва** стек от шрифтове с резервни опции за по-добра съвместимост с браузъри
**Обяснение на случващото се тук:**
- **Задава** шрифтово семейство за цялата страница чрез таргетиране на `<body>` елемента
- **Използва** стек от шрифтове с резервни опции за по-добра съвместимост с браузърите
- **Прилага** модерни системни шрифтове, които изглеждат добре на различни операционни системи
- **Гарантира**, че всички дъщерни елементи наследяват този шрифт, освен ако не са изрично заменени
- **Осигурява**, че всички вложени елементи наследяват този шрифт, освен ако не е изрично презаписан
Отворете инструментите за разработчици на браузъра (F12), отидете на таба Elements и инспектирайте вашия `<h1>` елемент. Ще видите, че той наследява шрифта от body:
Отворете инструменти за разработчици на вашия браузър (F12), отидете на раздел Elements и инспектирайте вашия `<h1>` елемент. Ще видите, че той наследява шрифтa от body:
✅ **Експеримент**: Опитайте да зададете други наследяеми свойства на `<body>` като `color`, `line-height` или `text-align`. Какво се случва с вашия заглавие и други елементи?
✅ **Време за експеримент**: Опитайте да зададете други наследяеми свойства на `<body>`, като `color`, `line-height` или `text-align`. Какво се случва с вашия заглавен елемент и други елементи?
> **Наследяеми свойства, които не са**: `margin`, `padding`, `border`, `width`, `height`, `position`
## Овладяване на селектори в CSS
### 🔄 **Педагогическа проверка**
**Разбиране на основите на CSS**: Преди да преминете към селектори, уверете се, че можете:
- ✅ Да обясните разликата между каскада и наследяване
- ✅ Да предскажете кой стил ще победи при конфликт на специфичност
- ✅ Да разпознаете кои свойства се наследяват от родителски елементи
- ✅ Да свързвате CSS файлове към HTML правилно
Селекторите в CSS са вашият начин да таргетирате конкретни елементи за стилизиране. Те работят като даване на точни указания - вместо да кажете "къщата", може да кажете "синята къща с червената врата на улица Мейпъл".
**Бърз тест**: Ако имате тези стилове, какъв цвят ще има `<h1>` в `<div class="special">`?
```css
div { color: blue; }
.special { color: green; }
h1 { color: red; }
```
*Отговор: Червен (селектор на елемент директно таргетира h1)*
## Овладяване на CSS селекторите
CSS предоставя различни начини за прецизност, и изборът на правилния селектор е като избор на подходящ инструмент за задачата. Понякога трябва да стилизирате всяка врата в квартала, а понякога само една конкретна врата.
CSS селекторите са вашият начин да таргетирате конкретни елементи за стилизиране. Те работят като даване на точни инструкции - вместо да казвате „къщата“, бихте казали „синята къща с червената врата на улица Мейпъл“.
### Селектори на елементи (Тагове)
CSS предоставя различни начини за избиране на елементи, а изборът на правилния селектор е като избора на правилния инструмент. Понякога трябва да стилизирате всички врати в квартала, а понякога само една конкретна врата.
Селекторите на елементи таргетират HTML елементи по техния таг. Теса идеални за задаване на основни стилове, които се прилагат широко на страницата:
### Селектори по елемент (таг)
Селекторите по елемент таргетират HTML елементи по тяхното име на таг. Теса идеални за задаване на базови стилове, които се прилагат широко из страницата:
```css
body {
@ -161,18 +251,18 @@ h1 {
```
**Разбиране на тези стилове:**
- **Задава** последователна типография за цялата страница с селектора `body`
- **Премахва** стандартните отстъпи и запълване на браузъра за по-добър контрол
- **Стилира** всички заглавни елементи с цвят, подравняване и разстояние
- **Използва** единици `rem` за мащабируемо и достъпнооразмеряване на шрифта
- **Задава** последователна типография за цялата страница чрез селектора `body`
- **Премахва** браузърните отстояния и падащи стойности за по-добър контрол
- **Стилира** всички заглавни елементи с цвят, подравняване и разстояния
- **Използва** единици `rem` за мащабируем и достъпен размер на шрифта
Докато селекторите на елементи работят добре за общо стилизиране, ще ви трябват по-специфични селектори, за да стилизирате индивидуални компоненти като растенията в вашия терариум.
Докато селекторите по елемент работят добре за общо стилизиране, ще ви трябват по-специфични селектори за стилизиране на отделни компоненти като растенията в терариума.
### ID селектори за уникални елементи
### Селектори по ID за уникални елементи
ID селекторите използват символа `#` и таргетират елементи със специфични атрибути `id`. Тъй като ID-тата трябва да бъдат уникални на страницата, те са идеални за стилизиране на индивидуални, специални елементи като контейнерите за растенията отляво и отдясно.
Селекторите по ID използват символа `#` и таргетират елементи с конкретни атрибути `id`. Тъй като ID-тата трябва да са уникални в една страница, те са перфектни за стилизиране на отделни, специални елементи като контейнерите за растенията вляво и вдясно.
Нека създадем стилизиране за контейнерите на терариума, където ще се намират растенията:
Нека създадем стилизиране за страничните контейнери на терариума, където ще се намират растенията:
```css
#left-container {
@ -198,14 +288,14 @@ ID селекторите използват символа `#` и таргет
}
```
**Ето какво постига този код:**
- **Позиционира** контейнерите в крайните леви и десни ръбове с помощта на `absolute` позициониране
- **Използва** единици `vh` (височина на изгледа) за адаптивна височина, която се променя според размера на екрана
- **Прилага** `box-sizing: border-box`, така че запълването да се включи в общата ширина
- **Премахва** ненужните единици `px` от стойности нула за по-чист код
- **Задава** лек фон, който е по-приятен за очите от ярко сивото
**Какво постига този код:**
- **Позиционира** контейнерите в най-лявата и най-дясната част чрез абсолютна позиция
- **Използва** `vh` (височина на изгледа) единици за адаптивна височина според размера на екрана
- **Прилага** `box-sizing: border-box`, така че падингът да се включва в общата ширина
- **Премахва** ненужни`px` единици от стойности с нула за по-чист код
- **Задава** мек фон, който е по-приятен за окото от твърдо сивото
✅ **Предизвикателство за качество на кода**: Забележете как този CSS нарушава принципа DRY (Несе повтаряй). Можете ли да го рефакторирате, използвайки както ID, така и клас?
✅ **Предизвикателство за качество на кода**: Забелязвате ли, че този CSS нарушава принципа DRY (Don't Repeat Yourself)? Можете ли да го рефакторирате, използвайки както ID, така и клас?
**Подобрен подход:**
```html
@ -233,24 +323,24 @@ ID селекторите използват символа `#` и таргет
}
```
### Селектори на класове за многократна употреба
### Класови селектори за многократно използване на стилове
Селекторите на класове използват символа `.` и са идеални, когато искате да приложите едни и същи стилове към множество елементи. За разлика от ID-тата, класовете могат да се използват многократно в целия HTML, което ги прави идеални за последователни стилови модели.
Класовите селектори използват символа `.` и са идеални, когато искате да приложите същите стилове към множество елементи. За разлика от ID-тата, класовете могат да се използват многократно в целия HTML, което ги прави подходящи за консистентни стилови шаблони.
В нашия терариум всяко растение се нуждае от подобно стилизиране, но също така се нуждае от индивидуално позициониране. Ще използваме комбинация от класове за общи стилове и ID-та за уникално позициониране.
В нашия терариум всяко растение се нуждае от подобно стилизиране, но също така и от индивидуално позициониране. Ще използваме комбинация от класове за споделени стилове и ID-та за уникално позициониране.
**Ето HTML структурата за всяко растение:**
```html
<divclass="plant-holder">
<imgclass="plant"alt="Decorative plant for terrarium"id="plant1"src="../../../../translated_images/plant1.d18b18ffe73da18f8b1ac7aba73b4050af52f4a0c9174aeac464b85123fc2850.bg.png" />
<imgclass="plant"alt="Decorative plant for terrarium"id="plant1"src="../../../../translated_images/plant1.d18b18ffe73da18f.bg.png" />
</div>
```
**Ключови елементи обяснени:**
**Обяснение на ключовите елементи:**
- **Използва** `class="plant-holder"` за последователно стилизиране на контейнера за всички растения
- **Прилага** `class="plant"` за общо стилизиране и поведение на изображението
- **Включва** уникално`id="plant1"` за индивидуално позициониране и взаимодействиес JavaScript
- **Осигурява** описателен alt текст за достъпност за хорас увредено зрение
- **Прилaга** `class="plant"` за споделен стил и поведение на изображенията
- **Включва** уникален `id="plant1"` за индивидуално позициониране и JavaScript взаимодействие
- **Осигурява** описателен alt текст за достъпност с екранни четци
Сега добавете тези стилове към вашия файл `style.css`:
@ -275,36 +365,52 @@ ID селекторите използват символа `#` и таргет
```
**Разбивка на тези стилове:**
- **Създава** относително позициониране за контейнера на растението, за да установи контекст за позициониране
- **Задава** височина на всеки контейнер за растения на 13%, за да се гарантира, че всички растения се побират вертикално без превъртане
- **Премества** контейнерите леко наляво, за да центрира по-добре растенията в техните контейнери
- **Позволява** растенията да се мащабират адаптивно с свойства `max-width` и `max-height`
- **Създава** относително позициониране за контейнера на растението, за да осигури контекст на позициониране
- **Задава** височина на всеки контейнер 13%, така че всички растения да се побират вертикално без скролиране
- **Изместване** на контейнерите леко наляво за по-добро центриране на растенията във вътрешността
- **Позволява** растенията да се мащабират адаптивно чрез свойства `max-width` и `max-height`
- **Използва** `z-index`, за да постави растенията над други елементи в терариума
- **Добавя** лек ефект при задържане с CSS преходи за по-добро взаимодействие с потребителя
- **Добавя** мек ефект при задържане с мишката чрез CSS преходи за по-добро взаимодействие с потребителя
✅ **Критично мислене**: Защо ни трябват както селектори `.plant-holder`, така и `.plant`? Какво би се случило, акосе опитаме да използваме само един?
✅ **Критично мислене**: Защо са необходими и двете селектори `.plant-holder` и `.plant`? Какво би се случило, ако използваме само един?
> 💡 **Дизайнерски модел**: Контейнерът (`.plant-holder`) контролира оформлението и позиционирането, докато съдържанието (`.plant`) контролира външния вид и мащабирането. Това разделение прави кода по-лесен за поддръжка и по-гъвкав.
> 💡 **Дизайнерски модел**: Контейнерът (`.plant-holder`) контролира оформлението и позиционирането, докато съдържанието (`.plant`) контролира външния вид и мащабирането. Тази разделеност прави кода по-поддържащ и гъвкав.
## Разбиране на позиционирането в CSS
Позиционирането в CSS е като да бъдете режисьор на сцена - вие решавате къде стои всеки актьор и как се движи по сцената. Някои актьори следват стандартната формация, докато други се нуждаят от специфично позициониране за драматичен ефект.
Позиционирането в CSS е като режисьор на театрална постановка – ви казва къде стои всеки актьор и как се движи на сцената. Някои актьори следват стандартното разположение, докато други изискват специфично позициониране за драматичен ефект.
След като разберете позиционирането, много предизвикателства с оформлението стават управляеми. Нуждаете се от навигационна лента, която остава в горната част, докато потребителите превъртат? Позиционирането се справя с това. Искате подсказка, която се появява на конкретно място? Това също е позициониране.
След като разберете позиционирането, много предизвикателства при оформлението стават управляеми. Искате ли навигационна лента, която остава на върха, когато потребителите скролват? Позиционирането се грижи за това. Искате ли подсказка, която се показва на конкретно място? Това също е позициониране.
### Петте стойности на позициониране
```mermaid
quadrantChart
title Стратегия за позициониране в CSS
x-axis Документен поток --> Премахнат от потока
y-axis Статична позиция --> Прецизен контрол
quadrant-1 Абсолютно
quadrant-2 Фиксирано
quadrant-3 Статично
quadrant-4 Залепващо
Static: [0.2, 0.2]
Relative: [0.3, 0.6]
Absolute: [0.8, 0.8]
Fixed: [0.9, 0.7]
Sticky: [0.5, 0.9]
```
| Стойност на позициониране | Поведение | Приложение |
| `fixed` | Позиционирасе спрямо изгледа на прозореца | Навигационни ленти, плаващи елементи |
| `sticky` | Превключва между relative и fixed според скролиране | Заглавия, които се зацепват при скролиране |
### Позициониране в нашия терариум
Нашият терариум използва стратегическа комбинация от типове позициониране, за да създаде желаното оформление:
Нашият терариум използва стратегическа комбинация от типове позициониране, за да постигне желаното оформление:
```css
/* Container positioning */
@ -326,8 +432,61 @@ ID селекторите използват символа `#` и таргет
}
```
**Разбиране на стратегията за
Нека изградим терариума стъпка по стъпка. Всеки елемент използва абсолютно позициониране и размери на база проценти за адаптивен дизайн:
**Разбиране на стратегията за позициониране:**
- **Абсолютните контейнери** се изваждат от нормалния поток и се закрепват към краищата на екрана
- **Относителните "plant-holder"** създават контекст за позициониране, като остават в потока на документа
- **Абсолютните "plant"** могат да се позиционират прецизно в рамките на относителните контейнери
- **Тази комбинация** позволява растенията да се нареждат вертикално и да се позиционират индивидуално
> 🎯 **Защо е важно:** Елементите `plant`се нуждаят от абсолютна позиция, за да станат плъзгащи се в следващия урок. Абсолютното позициониране ги изважда от нормалния поток, което позволява интерактивност за влачене и пускане.
✅ **Време за експеримент:** Опитайте да променяте стойностите на позициониране и наблюдавайте резултатите:
- Какво се случва, ако промените `.container` от `absolute` на `relative`?
- Как се променя оформлението, ако `.plant-holder` използва `absolute` вместо `relative`?
- Какво се случва, когато превключите `.plant` на `relative` позициониране?
### 🔄 **Педагогическа проверка**
**Майсторство с позициониране в CSS**: Направете пауза, за да проверите разбирането си:
- ✅ Можете ли да обясните защо растенията се нуждаят от абсолюно позициониране за drag-and-drop?
- ✅ Разбирате ли как относителните контейнери създават контекст за позициониране?
- ✅ Защо страничните контейнери използват абсолюно позициониране?
- ✅ Какво би станало, ако изобщо премахнете декларациите за позициониране?
**Връзка с реалния свят**: Помислете как позиционирането в CSS отразява реалния свят:
- **Статично**: Книги на рафт (естествен ред)
- **Относително**: Преместване на книга леко, но запазване на мястото й
- **Абсолютно**: Поставяне на книгоразделител на точна страница
- **Фиксирано**: Лепяща бележка, която остава видима докато листите страниците
## Създаване на терариум с CSS
Сега ще построим стъклен буркан, използвайки само CSS - без нужда от изображения или графичен софтуер.
Създаването на реалистично изглеждащо стъкло, сенки и дълбочина с позициониране и прозрачност демонстрира визуалните възможности на CSS. Тази техника отразява как архитектите от движение Баухаус са използвали прости геометрични фигури за създаване на сложни, красиви конструкции. След като разберете тези принципи, ще разпознаете CSS техниките зад много уеб дизайни.
```mermaid
flowchart LR
A[Капак на буркана] --> E[Завършен терариум]
B[Стени на буркана] --> E
C[Слой пръст] --> E
D[Дъно на буркана] --> E
F[Ефекти на стъкло] --> E
A1["50% ширина<br/>5% височина<br/>Горна позиция"] --> A
B1["60% ширина<br/>80% височина<br/>Заоблени ъгли<br/>0.5 прозрачност"] --> B
C1["60% ширина<br/>5% височина<br/>Тъмнокафяво<br/>Долен слой"] --> C
D1["50% ширина<br/>1% височина<br/>Долна позиция"] --> D
F1["Нежни сенки<br/>Прозрачност<br/>Слоеве по Z-индекс"] --> F
style E fill:#d1e1df,stroke:#3a241d
style A fill:#e8f5e8
style B fill:#e8f5e8
style C fill:#8B4513
style D fill:#e8f5e8
```
### Създаване на компонентите на стъкления буркан
Нека изградим буркана на терариума на части. Всяка част използва абсолюно позициониране и размери, базирани на проценти за отзивчив дизайн:
```css
.jar-walls {
@ -380,88 +539,197 @@ ID селекторите използват символа `#` и таргет
```
**Разбиране на конструкцията на терариума:**
- **Използва** размери на база проценти за адаптивно мащабиране на всички размери на екрана
- **Позиционира** елементите абсолютно, за да ги подреди и подравни прецизно
- **Прилага** различни стойности на прозрачност за създаване на ефект на стъклена прозрачност
- **Използва** `z-index` за наслояване, така че растенията да изглеждат вътре в буркана
- **Добавя** финни сенки и усъвършенстван радиус на рамката за по-реалистичен вид
- **Използва** размери в проценти за отзивчиво мащабиране на всички размери на екрана
- **Позиционира** елементите абсолютно, за да ги подредим и подравним точно
- **Прилaга** различни стойности на прозрачност за създаване на ефект на стъкленост
- **Изпълнява** слоеве чрез `z-index`, така че растенията да се появяват вътре в буркана
- **Добавя** леки сенки и фина граница с радиус за по-реалистичен вид
### Адаптивен дизайн с проценти
### Отзивчив дизайн с проценти
Обърнете внимание как всички размери използват проценти вместо фиксирани пикселни стойности:
Забележете как всички размери използват проценти вместо фиксирани пиксели:
**Защо това е важно:**
- **Осигурява** пропорционално мащабиране на терариума на всякакъв размер екран
**Защо е важно:**
- **Гарантира**, че терариумът се мащабира пропорционално на всеки размер екран
- **Поддържа** визуалните връзки между компонентите на буркана
- **Гарантира** последователно изживяване от мобилни телефони до големи настолни монитори
- **Позволява** дизайнът да се адаптира без да нарушава визуалното оформление
- **Осигурява** последователно изживяване от мобилни телефони до големи десктоп екрани
- **Позволява** дизайнът да се адаптира без да нарушава визуалния изглед
### CSS единици в действие
Използваме `rem` единици за радиуса на рамката, които се мащабират спрямо основния размер на шрифта. Това създава по-достъпни дизайни, които уважават предпочитанията на потребителя за шрифт. Научете повече за [CSS относителни единици](https://www.w3.org/TR/css-values-3/#font-relative-lengths) в официалната спецификация.
Използваме единици `rem` за радиуса на границата, които се мащабират спрямо основния размер на шрифта. Това създава по-достъпни дизайни, които уважават настройките на шрифтовете на потребителя. Прочетете повече за [относителните CSS единици](https://www.w3.org/TR/css-values-3/#font-relative-lengths) в официалната спецификация.
✅ **Визуален експеримент**: Опитайте да промените тези стойности и наблюдавайте ефекта:
- Променете прозрачността на буркана от 0.5 на 0.8 – как това влияе на вида на стъклото?
- Регулирайте цвета на пръстта от `#3a241d` на `#8B4513`– какъв визуален ефект има това?
- Променете `z-index` на пръстта на 2 – какво става с подреждането на слоевете?
### 🔄 **Педагогическа проверка**
**Разбиране на визуален дизайн с CSS**: Потвърдете усвояването си на визуалния CSS:
- ✅ Как размерите в проценти създават отзивчив дизайн?
- ✅ Защо прозрачността създава ефекта на стъклена прозрачност?
- ✅ Каква роля играе z-index в слоевете на елементите?
- ✅ Как радиусът на границата формира формата на буркана?
✅ **Визуален експеримент**: Опитайте да промените тези стойности и наблюдавайте ефектите:
- Променете прозрачността на буркана от 0.5 на 0.8 – как това влияе на външния вид на стъклото?
- Настройте цвета на почвата от `#3a241d` на `#8B4513`– какъв визуален ефект има това?
- Модифицирайте `z-index` на почвата на 2 – какво се случва с наслояването?
**Принцип на дизайна**: Забележете как изграждаме сложни визуални ефекти от прости форми:
1. **Правоъгълници** → **Заоблени правоъгълници** → **Компоненти на буркана**
Използвайте режима Agent, за да завършите следното предизвикателство:
Използвайте режим Agent, за да завършите следното предизвикателство:
**Описание:** Създайте CSS анимация, която кара растенията в терариума да се люлеят леко напред-назад, симулирайки ефект на естествен бриз. Това ще ви помогне да практикувате CSS анимации, трансформации и ключови кадри, като същевременно подобрите визуалната привлекателност на вашия терариум.
**Описание:** Създайте CSS анимация, която кара растенията в терариума леко да се люлеят напред-назад, симулирайки лек бриз. Това ще ви помогне да практикувате CSS анимации, трансформации и ключови кадри, като същевременно подобрите визуалната привлекателност на терариума.
**Подсказка:** Добавете CSS анимации с ключови кадри, за да направите растенията в терариума да се люлеят леко отстрани. Създайте анимация на люлеене, която леко завърта всяко растение (2-3 градуса) наляво и надясно с продължителност от 3-4 секунди и я приложете към класа `.plant`. Уверете се, че анимацията се повтаря безкрайно и има функция за изглаждане за естествено движение.
**Задача:** Добавете CSS ключови кадри, за да накарате растенията в терариума да се люлеят леко отстрани на страна. Създайте анимация на люлеене, която завърта всяко растение леко (2-3 градуса) наляво и надясно с продължителност 3-4 секунди, и я приложете към класа `.plant`. Уверете се, че анимацията се повтаря безкрайно и има функция за плавност за естествено движение.
Научете повече за [режим Agent](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
Научете повече за [режим agent](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
## 🚀 Предизвикателство: Добавяне на отражения върху стъклото
## 🚀 Предизвикателство: Добавяне на отразявания върху стъклото
Готови ли сте да подобрите вашия терариум с реалистични отражения върху стъклото? Тази техника ще добави дълбочина и реализъм към дизайна.
Готови ли сте да подобрите терариума сис реалистични отражения върху стъклото? Тази техника ще добави дълбочина и реализъм на дизайна.
Ще създадете фини отблясъци, които симулират как светлината се отразява от стъклени повърхности. Този подход е подобен на начина, по който ренесансови художници като Ян ван Ейк използват светлина и отражение, за да направят рисуваното стъкло да изглежда триизмерно. Ето какво целите:
Ще създадете нежни отблясъци, които симулират как светлината се отразява от стъклени повърхности. Този подход е подобен на техниката на ренесансови художници като Ян ван Ейк, които използвали светлина и отражения, за да направят изрисуваното стъкло триизмерно. Ето какво трябва да постигнете:
- 🎯 [CSS Battle](https://cssbattle.dev/) - тествайте CSS уменията си с кодови предизвикателства
### Допълнително обучение
За цялостни основи на CSS, завършете този модул на Microsoft Learn: [Стилизирайте вашето HTML приложение с CSS](https://docs.microsoft.com/learn/modules/build-simple-website/4-css-basics/?WT.mc_id=academic-77807-sagibbon)
За изчерпателни CSS основи, завършете този модул на Microsoft Learn: [Стил на HTML приложение с CSS](https://docs.microsoft.com/learn/modules/build-simple-website/4-css-basics/?WT.mc_id=academic-77807-sagibbon)
### ⚡ **Какво можете да направите следващите 5 минути**
- [ ] Отворете DevTools и инспектирайте CSS стилове на който и да е сайт чрез панела Elements
- [ ] Създайте прост CSS файл и го свържете с HTML страница
- [ ] Опитайте да промените цветове чрез различни методи: hex, RGB, именовани цветове
- [ ] Практикувайте box model, като добавите padding и margin към div
### 🎯 **Какво можете да постигнете този час**
- [ ] Завършете квиза след урока и прегледайте CSS основите
- [ ] Стиловайте HTML страницата с шрифтове, цветове и разстояния
- [ ] Създайте прост layout с flexbox или grid
- [ ] Експериментирайте с CSS преходи за плавни ефекти
- [ ] Практикувайте отзивчив дизайн с медиен заявки
### 📅 **Вашето седмично CSS приключение**
- [ ] Завършете задачата за стилизиране на терариума с творчески подход
- [ ] Усъвършенствайте CSS Grid като изградите фото галерия
- [ ] Научете CSS анимации, за да вдъхнете живот на дизайните си
- [ ] Изследвайте CSS препроцесори като Sass или Less
- [ ] Изучавайте принципи на дизайна и ги прилагайте в CSS
- [ ] Анализирайте и пресъздавайте интересни дизайни от онлайн
### 🌟 **Вашето месечно майсторство в дизайна**
- [ ] Изградете пълна система за отзивчив уеб дизайн
- [ ] Научете CSS-in-JS или utility-first фреймуъркове като Tailwind
- [ ] Приносете към open source проекти с подобрения в CSS
- [ ] Усъвършенствайте напреднали CSS концепции като персонализирани свойства и containment
- [ ] Създайте библиотеки с модулен CSS и преизползваеми компоненти
- [ ] Наставлявайте други в изучаването на CSS и споделяйте дизайнерски знания
## 🎯 Вашата времева линия на майсторство в CSS
```mermaid
timeline
title Прогрес в изучаването на CSS
section Основи (10 минути)
Връзка с файл: Свързване на CSS с HTML
: Разбиране на правилата на каскадата
: Научаване на основите на наследяването
section Селектора (15 минути)
Насочване към елементи: Селектори по елементи
: Шаблони за класове
: Специфичност на ID
: Комбинатори
section Кутия модел (20 минути)
Основи на оформлението: Отстъпи и запълване
: Свойства на рамката
: Оразмеряване на съдържанието
: Поведение на box-sizing
section Позициониране (25 минути)
Разположение на елементи: Статично срещу относително
: Абсолютно позициониране
: Слоеве с Z-index
: Отзивчиви единици
section Визуален дизайн (30 минути)
Майсторство в стилизирането: Цветове и непрозрачност
: Сенки и ефекти
: Преходи
: Свойства на трансформациите
section Отзивчив дизайн (45 минути)
Поддръжка на множество устройства: Медиен запитвания
: Гъвкави оформления
: Подход mobile-first
: Оптимизация на изгледа
section Напреднали техники (1 седмица)
Модерен CSS: Flexbox оформления
: CSS Grid системи
: Персонализирани свойства
: Ключови кадри за анимации
section Професионални умения (1 месец)
Архитектура на CSS: Шаблони за компоненти
: Поддържам код
: Оптимизация на производителността
: Кръстосана съвместимост с браузъри
```
### 🛠️ Обобщение на CSS арсенала ви
След като завършихте този урок, вече притежавате:
- **Разбиране на каскадата**: Как стиловете наследяват и презаписват един друг
- **Майсторство на селекторите**: Точно таргетиране с елементи, класове и ID-та
- **Умения за позициониране**: Стратегическо поставяне и слоеве на елементите
- **Визуален дизайн**: Създаване на стъклени ефекти, сенки и прозрачност
- **Отзивчиви техники**: Оформления на базата на проценти, които се адаптират към всеки екран
- **Организация на кода**: Чист и поддържан CSS
- **Модерни практики**: Използване на относителни единици и достъпни дизайнерски модели
**Следващи стъпки**: Вашият терариум вече има структура (HTML) и стил (CSS). Последният урок ще добави интерактивност с JavaScript!
## Задание
## Задача
[Рефакториране на CSS](assignment.md)
[CSS Рефакториране](assignment.md)
---
**Отказ от отговорност**:
Този документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Не носим отговорност за недоразумения или погрешни интерпретации, произтичащи от използването на този превод.
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Отказ от отговорност**:
Този документ е преведен с помощта на AI преводаческия сервис [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи могат да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Не носим отговорност за никакви недоразумения или погрешни тълкувания, произтичащи от използването на този превод.
# Проект Терариум Част 3: Манипулация с DOM и JavaScript Closures
# Terrarium Project Част 3: Манипулация на DOM и JavaScript замиквания

> Скица от [Tomomi Imura](https://twitter.com/girlie_mac)
```mermaid
journey
title Вашето JavaScript DOM пътешествие
section Основи
Разберете DOM: 3: Student
Научете闭包: 4: Student
Свържете елементи: 4: Student
section Взаимодействие
Настройте събития за плъзгане: 4: Student
Следете координатите: 5: Student
Обработвайте движение: 5: Student
section Финализиране
Добавете почистване: 4: Student
Тествайте функционалността: 5: Student
Завършете терариума: 5: Student
```

> Скетчноут от [Tomomi Imura](https://twitter.com/girlie_mac)
Добре дошли в една от най-интересните области на уеб разработката - създаването на интерактивност! Document Object Model (DOM) е като мост между вашия HTML и JavaScript, и днес ще го използваме, за да вдъхнем живот на вашия терариум. Когато Тим Бърнърс-Лий създаде първия уеб браузър, той си представяше уеб, където документите могат да бъдат динамични и интерактивни - DOM прави тази визия възможна.
Добре дошли в един от най-ангажиращите аспекти на уеб разработката - правенето на нещата интерактивни! Document Object Model (DOM) е като мост между вашия HTML и JavaScript, и днес ще го използваме, за да вдъхнем живот на вашия терариум. Когато Тим Бернърс-Лий създава първия уеб браузър, той си представя уеб, където документите могат да бъдат динамични и интерактивни - DOM прави тази визия възможна.
Ще разгледаме и JavaScript closures, които може да звучат плашещо в началото. Помислете за closures като за "джобове на паметта", където вашите функции могат да запомнят важна информация. Това е като всяко растение в терариума да има собствен запис на данни, за да следи позицията си. До края на този урок ще разберете колко естествени и полезни са те.
Ще разгледаме и JavaScript замиквания, които може да звучат страховито в началото. Мислете за замикванията като създаване на "джобове за памет", където вашите функции могат да запомнят важна информация. Това е като всяко растение във вашия терариум да има свой собствен запис за позицията си. В края на този урок ще разберете колко естествени и полезни са те.
Ето какво ще изградим: терариум, в който потребителите могат да местят растенията навсякъде, където пожелаят. Ще научите техники за манипулация с DOM, които захранват всичко - от качване на файлове чрез влачене и пускане до интерактивни игри. Нека вдъхнем живот на вашия терариум.
Ето какво ще създадем: терариум, в който потребителите могат да плъзгат и пускат растения навсякъде където искат. Ще научите техниките за манипулация на DOM, които захранват всичко - от плъзгане и пускане на файлове до интерактивни игри. Нека оживим вашия терариум.
## Разбиране на DOM: Вашият портал към интерактивни уеб страници
## Разбиране на DOM: Вратата ви към интерактивнитеуеб страници
Document Object Model (DOM) е начинът, по който JavaScript комуникира с вашите HTML елементи. Когато браузърът ви зареди HTML страница, той създава структурирано представяне на тази страница в паметта - това е DOM. Представете си го като семейно дърво, където всеки HTML елемент е член на семейството, който JavaScript може да достъпи, модифицира или пренареди.
Document Object Model (DOM) е начинът, по който JavaScript комуникира с вашите HTML елементи. Когато браузърът зареди HTML страница, той създава структурирано представяне на тази страница в паметта - това е DOM. Мислете за него като за родословно дърво, където всеки HTML елемент е член на семейството, до който JavaScript може да има достъп, да го променя или пренарежда.
Манипулацията с DOM трансформира статичните страници в интерактивни уебсайтове. Всеки път, когато видите бутон, който променя цвета си при задържане, съдържание, което се обновява без презареждане на страницата, или елементи, които можете да местите, това е работа на манипулацията с DOM.
Манипулацията на DOM превръща статични страници в интерактивни уебсайтове. Всеки път когато видите бутон да променя цвят при задържане на мишката, съдържание дасе обновява без презареждане на страницата или елементи, които можете да плъзгате, това е DOM манипулация в действие.

```mermaid
flowchart TD
A["Документ"] --> B["HTML"]
B --> C["Главна част"]
B --> D["Тяло"]
C --> E["Заглавие"]
C --> F["Мета тагове"]
D --> G["H1: Моят терариум"]
D --> H["Div: Контейнер на страницата"]
H --> I["Div: Ляв контейнер"]
H --> J["Div: Десен контейнер"]
H --> K["Div: Терариум"]
I --> L["Растителни елементи 1-7"]
J --> M["Растителни елементи 8-14"]
L --> N["img#plant1"]
L --> O["img#plant2"]
M --> P["img#plant8"]
M --> Q["img#plant9"]
style A fill:#e1f5fe
style B fill:#f3e5f5
style D fill:#e8f5e8
style H fill:#fff3e0
style N fill:#ffebee
style O fill:#ffebee
style P fill:#ffebee
style Q fill:#ffebee
```

> Представяне на DOM и HTML маркировката, която го реферира. От [Olfa Nasraoui](https://www.researchgate.net/publication/221417012_Profile-Based_Focused_Crawler_for_Social_Media-Sharing_Websites)
**Ето какво прави DOM мощен:**
- **Осигурява** структуриран начин за достъп до всеки елемент на страницата ви
- **Позволява** динамично обновяване на съдържанието без презареждане на страницата
- **Реагира** в реално време на взаимодействията на потребителя като кликове и влачене
- **Създава** основата за модерни интерактивни уеб приложения
- **Осигурява** структурирана възможност за достъп до всеки елемент на вашата страница
- **Позволява** динамични обновявания на съдържанието без презареждане
- **Позволява** отговор в реално време на взаимодействия като кликвания и плъзгане
- **Създава** основата за съвременни интерактивни уеб приложения
## JavaScript Closures: Създаване на организиран и мощен код
## JavaScript замиквания: Създаване на организиран, мощен код
[JavaScript closure](https://developer.mozilla.org/docs/Web/JavaScript/Closures) е като да дадете на функцията собствено частно пространство с постоянна памет. Помислете как финките на Дарвин на островите Галапагос са развили специализирани човки според специфичната си среда - closures работят по подобен начин, създавайки специализирани функции, които "запомнят" своя специфичен контекст дори след като родителската функция е приключила.
[JavaScript замикване](https://developer.mozilla.org/docs/Web/JavaScript/Closures) е като да дадете на функция собствено частно работно пространство с постоянна памет. Помислете как Darwin-овите враноглави птици на Галапагоските острови са развили специализирани човки според средата си - замикванията работят по същия начин, създавайки специализирани функции, които "помнят" своя конкретен контекст дори след като родителската им функция приключи.
В нашия терариум closures помагат на всяко растение да запомни собствената си позиция независимо. Този модел се среща навсякъде в професионалната JavaScript разработка, което го прави ценна концепция за разбиране.
В нашия терариум замикванията помагат на всяко растение да помни собствената си позиция независимо. Този модел сепоявява във всички професионални JavaScript разработки, правейки го важна концепция за разбиране.
> 💡 **Разбиране на Closures**: Closures са значима тема в JavaScript, и много разработчици ги използват години наред, преди напълно да разберат всички теоретични аспекти. Днес ще се фокусираме върху практическото приложение - ще видите как closures естествено се появяват, докато изграждаме нашите интерактивни функции. Разбирането ще се развие, докато виждате как те решават реални проблеми.
> 💡 **Разбиране на замикванията**: Замикванията са важна тема в JavaScript, и много разработчици ги използват години преди да разберат напълно всички теоретични аспекти. Днес се фокусираме върху практическото приложение - ще видите как замикванията естествено изникват докато изграждаме нашите интерактивни функции. Разбирането ще се развива докато виждате как те решават реални проблеми.


> Представяне на DOM и HTML маркировката, която го реферира. От [Olfa Nasraoui](https://www.researchgate.net/publication/221417012_Profile-Based_Focused_Crawler_for_Social_Media-Sharing_Websites)
В този урок ще завършим нашия интерактивен проект за терариум, като създадем JavaScript, който ще позволи на потребителя да манипулира растенията на страницата.
В този урок ще завършим нашия интерактивен терариум проект, като създадем JavaScript, който ще позволи на потребителя да манипулира растенията на страницата.
## Преди да започнем: Подготовка за успех
Ще ви трябват вашите HTML и CSS файлове от предишните уроци за терариум - предстои да направим този статичен дизайн интерактивен. Ако се присъединявате за първи път, завършването на тези уроци първо ще ви предостави важен контекст.
Ще ви трябват HTML и CSS файловете от предишните уроци за терариума - предстои да направим този статичен дизайн интерактивен. Ако се присъединявате за първи път, първо преминаването през тези уроци ще ви предостави важен контекст.
Ето какво ще изградим:
- **Плавно влачене и пускане** за всички растения в терариума
- **Проследяване на координати**, за да запомнят растенията своите позиции
- **Пълно интерактивно интерфейс** с помощта на vanilla JavaScript
- **Чист, организиран код** с използване на closure модели
- **Плавно плъзгане и пускане** за всички растения в терариума
- **Проследяване на координати**, за да помнят растенията позициите си
- **Пълно интерактивно интерфейс** с помощта на чист JavaScript
- **Чист, организиран код** използващ шаблони за замиквания
## Настройка на вашия JavaScript файл
Нека създадем JavaScript файла, който ще направи вашия терариум интерактивен.
**Стъпка 1: Създайте вашия скрипт файл**
**Стъпка 1: Създайте скриптовия файл**
В папката на вашия терариум създайте нов файл, наречен `script.js`.
В папката на терариума си създайте нов файл, наречен `script.js`.
**Стъпка 2: Свържете JavaScript към вашия HTML**
**Стъпка 2: Свържете JavaScript с вашия HTML**
Добавете този `<script>` таг в секцията `<head>` на вашия `index.html` файл:
Добавете тази скрипт таг в секцията `<head>` на вашия `index.html` файл:
```html
<scriptsrc="./script.js"defer></script>
```
**Защо атрибутът `defer`е важен:**
- **Осигурява**, че вашият JavaScript ще изчака, докато целият HTML бъде зареден
- **Предотвратява** грешки, при които JavaScript търси елементи, които още не са готови
- **Гарантира**, че всички елементи на растениятаса налични за взаимодействие
- **Осигурява** по-добра производителност, отколкото поставянето на скриптове в долната част на страницата
- **Гарантира** че JavaScript чакa докато целият HTML е зареден
- **Предпазва** от грешки, когато JavaScript търси елементи, които все още не са заредени
- **Гарантира** че всички растителни елементиса налични за взаимодействие
- **Осигурява** по-добра производителност в сравнение с поставяне на скриптове в края на страницата
> ⚠️ **Важна бележка**: Атрибутът `defer` предотвратява често срещани проблеми с времето. Без него JavaScript може да се опита да достъпи HTML елементи преди те да бъдат заредени, което води до грешки.
> ⚠️ **Важно**: Атрибутът `defer` предотвратява типични проблеми с времето. Без него, JavaScript може да се опита да достъпи HTML елементи преди да са заредени, водейки до грешки.
---
## Свързване на JavaScript свашите HTML елементи
## Свързване на JavaScript с HTML елементите
Преди да направим елементите влачими, JavaScript трябва да ги намери в DOM. Представете си това като система за каталогизиране в библиотека - след като имате каталожния номер, можете да намерите точно книгата, която ви трябва, и да получите достъп до цялото й съдържание.
Преди да направим елементите за плъзгане, JavaScript трябва да ги намери в DOM. Мислете за това като за библиотечна каталогизация - когато имате каталожния номер, можете да намерите точно книгата, която ви трябва, и да достъпите целия й съдържание.
Ще използваме метода `document.getElementById()`, за да направим тези връзки. Това е като да имате прецизна система за архивиране - предоставяте ID и тя намира точно елемента, който ви трябва в HTML.
Ще използваме метода `document.getElementById()`, за да направим тези връзки. Това е като точна система за подреждане - подавате ID, и тя намира точно елемента, който ви трябва в HTML.
### Активиране на функцията за влачене за всички растения
### Активиране на функционалност за плъзгане за всички растения
Добавете този код към вашия файл`script.js`:
Добавете този код във файла си`script.js`:
```javascript
// Enable drag functionality for all 14 plants
// Активиране на функцията за плъзгане за всички 14 растения
- **Намира** всеки елемент на растение в DOM, използвайки уникалния му ID
- **Извлича** JavaScript референция към всеки HTML елемент
- **Предава** всеки елемент на функцията `dragElement` (която ще създадем след малко)
- **Подготвя** всяко растение за взаимодействие чрез влачене и пускане
- **Свързва** структурата на HTML с функционалността на JavaScript
- **Намира** всеки растителен елемент в DOM чрез уникалния му ID
- **Вземa** JavaScript препратка към всеки HTML елемент
- **Подава** всеки елемент на функция `dragElement` (която ще създадем след това)
- **Подготвя** всяко растение за взаимодействие с плъзгане и пускане
- **Свързва** вашата HTML структура с JavaScript функционалност
> 🎯 **Защо използваме ID, а не класове?** ID-та осигуряват уникални идентификатори за конкретни елементи, докато CSS класове са предназначени за стилизиране на групи елементи. Когато JavaScript трябва да манипулира отделни елементи, ID-тата дават необходимата прецизност и ефективност.
> 🎯 **Защо да използваме ID вместо класове?** ID предоставят уникални идентификатори за конкретни елементи, докато CSS класовете са предназначени за стилизиране на групи от елементи. Когато JavaScript трябва да манипулира индивидуални елементи, ID предлагат прецизността и производителността, от които се нуждаем.
> 💡 **Профи съвет**: Забележете, че извикваме `dragElement()` за всяко растение поотделно. Този подход гарантира, че всяко растение получава собствено независимо поведение за плъзгане, което е съществено за гладко потребителско взаимодействие.
> 💡 **Полезен съвет**: Забележете как извикваме `dragElement()` за всяко растение поотделно. Този подход гарантира, че всяко растение получава собствено независимо поведение при влачене, което е от съществено значение за гладкото взаимодействие с потребителя.
### 🔄 **Педагогическа проверка**
**Разбиране на връзката с DOM**: Преди да преминете към функционалността за плъзгане, уверете се, че можете да:
- ✅ Обясните как `document.getElementById()` намира HTML елементи
- ✅ Разберете защо използваме уникални ID-та за всяко растение
- ✅ Опишете ролята на атрибута `defer` в скрипт таговете
- ✅ Разпознаете как JavaScript и HTML се свързват чрез DOM
**Бърз самотест**: Какво би се случило, ако два елемента имат еднакъв ID? Защо `getElementById()` връща само един елемент?
*Отговор: ID-тата трябва да са уникални; ако са дублирани, се връща само първият елемент*
---
## Създаване на Closure за Drag Element
## Създаване на замикване за dragElement
Сега ще създадем сърцето на нашата функционалност за влачене: closure, който управлява поведението на влачене за всяко растение. Този closure ще съдържа множество вътрешни функции, които работят заедно, за да проследяват движенията на мишката и да актуализират позициите на елементите.
Сега ще създадем сърцето на нашата функционалност за плъзгане: замикване, което управлява поведението на плъзгане за всяко растение. Това замикване ще съдържа няколко вътрешни функции, които работят заедно, за да следят движението на мишката и да обновяват позициите на елементите.
Closures са идеални за тази задача, защото ни позволяват да създадем "частни" променливи, които се запазват между извикванията на функции, като дават на всяко растение собствена независима система за проследяване на координати.
Замикванията са перфектни за тази задача, защото ни позволяват да създадем "частни" променливи, които се запазват между извикванията на функции, давайки на всяко растение собствена независима система за проследяване на координати.
### Разбиране на Closures с прост пример
### Разбиране на замиквания чрез прост пример
Нека демонстрираме closuresс прост пример, който илюстрира концепцията:
Нека демонстрирам замикванияс прост пример, който илюстрира концепцията:
```javascript
function createCounter() {
let count = 0; // This is like a private variable
let count = 0; // Това е като частна променлива
function increment() {
count++; // The inner function remembers the outer variable
count++; // Вътрешната функция помни външната променлива
return count;
}
return increment; // We're giving back the inner function
- **Създава** частна променлива `count`, която съществува само в този closure
- **Вътрешната функция** може да достъпва и модифицира тази външна променлива (механизмът на closure)
- **Когато връщаме** вътрешната функция, тя запазва връзката си с тези частни данни
- **Дори след като** `createCounter()` приключи изпълнението си, `count`се запазва и помни стойността си
**Ето какво се случва в този шаблон на замикване:**
- **Създава** частна променлива `count`, която съществува само в това замикване
- **Вътрешната функция** може да достъпва и променя външната променлива (механизъм на замикването)
- **Когато връщаме** вътрешната функция, тя запазва връзката си с тази частна информация
- **Дори след** `createCounter()` да завърши изпълнението, `count` остава и помни стойността си
### Защо Closures са идеални за функционалността на влачене
### Защо замикванията са идеални за функционалността за плъзгане
За нашия терариум всяко растение трябва да запомни текущите си координати. Closures предоставят идеалното решение:
За нашия терариум всяко растение трябва да помни текущите си координати. Замикванията предоставят идеално решение:
**Основни предимства за нашия проект:**
- **Запазват** частни променливи за позицията на всяко растение независимо
- **Съхраняват** данни за координатите между събитията на влачене
- **Предотвратяват** конфликти на променливи между различни влачими елементи
- **Създават** чиста и организирана структура на кода
**Ключови ползи за нашия проект:**
- **Поддържа** частни променливи за позиция за всяко растение независимо
- **Запазва** координатните данни между събития за плъзгане
- **Предпазва** от конфликти между променливи при различните плъзгащи се елементи
- **Създава** чиста, организирана структура на кода
> 🎯 **Цел на обучението**: Нее нужно да овладявате всеки аспект на closures точно сега. Фокусирайте се върху това да видите как те помагат за организиране на кода и поддържане на състояние за функционалността на влачене.
> 🎯 **Цел на обучението**: Нее нужно да овладявате всеки аспект на замикванията веднага. Фокусирайте се върху това как помагат да организираме кода и да поддържаме състояние за функционалността за плъзгане.
Сега нека изградим основната функция, която ще управлява цялата логика на влачене. Добавете тази функция под декларациите на елементите на растенията:
Сега нека изградим основната функция, която ще управлява цялата логика на плъзгане. Добавете тази функция под декларациите за растителните елементи:
```javascript
function dragElement(terrariumElement) {
// Initialize position tracking variables
let pos1 = 0, // Previous mouse X position
pos2 = 0, // Previous mouse Y position
pos3 = 0, // Current mouse X position
pos4 = 0; // Current mouse Y position
// Инициализиране на променливи за проследяване на позицията
let pos1 = 0, // Предишна позиция на мишката по X
pos2 = 0, // Предишна позиция на мишката по Y
pos3 = 0, // Текуща позиция на мишката по X
pos4 = 0; // Текуща позиция на мишката по Y
// Set up the initial drag event listener
// Настройка на първоначалния слушател за събитие за плъзгане
terrariumElement.onpointerdown = pointerDrag;
}
```
**Разбиране на системата за проследяване на позицията:**
- **`pos1` и `pos2`**: Съхраняват разликата между старите и новите позиции на мишката
- **`pos3` и `pos4`**: Проследяват текущите координати на мишката
- **`terrariumElement`**: Конкретният елемент на растение, който правим влачим
- **`pos1` и `pos2`**: съхраняват разликата между старите и новите координати на мишката
- **`pos3` и `pos4`**: следят текущите координати на мишката
- **`terrariumElement`**: конкретният растителен елемент, който правим плъзгащ се
- **`onpointerdown`**: събитието, което задейства началото на плъзгане
**Ето как работи шаблонът на замикването:**
- **Създава** частни променливи за позиция за всеки растителен елемент
- **Поддържа** тези променливи през целия жизнен цикъл на плъзгането
- **Гарантира** че всяко растение следи собствените си координати независимо
- **Осигурява** чист интерфейс чрез функцията `dragElement`
### Защо използваме pointer събития?
Може да се чудите защо използваме `onpointerdown` вместо по-популярния `onclick`. Ето причините:
| Тип събитие | Най-подходящо за | Недостатък |
|-------------|------------------|------------|
| `onclick` | Прости кликвания на бутон | Не поддържа плъзгане (само клик и отпускане) |
| `onpointerdown` | Мишка и докосване | По-нова технология, но вече добре поддържана |
| `onmousedown` | Само за мишка на десктоп | Не покрива мобилни устройства |
**Защо pointer събитията са идеални за нашия проект:**
- **Работи отлично** независимо дали потребителят използва мишка, пръст или стилус
- **Същото усещане** на лаптоп, таблет или телефон
- **Управлява** действителното плъзгане (не само кликване)
- **Осигурява** плавно преживяване, което потребителите очакват от съвременни уеб приложения
> 💡 **Подготовка за бъдещето**: Pointer събитията са съвременният начин за обработка на взаимодействия. Вместо да пишете отделен код за мишка и докосване, получавате и двете безплатно. Много удобно, нали?
### 🔄 **Педагогическа проверка**
**Разбиране на събитията**: Спирайте за момент и проверете разбирането си:
- ✅ Защо използваме pointer събития вместо mouse събития?
- ✅ Как замикващите променливи се запазват между извиквания на функции?
- ✅ Каква роля играе `preventDefault()` при плавното плъзгане?
- ✅ Защо прикачваме слушатели към документа вместо към отделни елементи?
**Връзка с реалния свят**: Помислете за интерфейсите за плъзгане и пускане, които използвате ежедневно:
- **Качване на файлове**: плъзгане на файлове в прозорец на браузъра
- **Канбан дъски**: преместване на задачи между колони
- **Галерии с изображения**: пренареждане на снимки
- **Мобилни интерфейси**: плъзгане и докосване на екрана
---
## Функцията pointerDrag: Започване на плъзгане
Когато потребител натисне върху растение (с мишка или докосване), функцията `pointerDrag` влезе в действие. Тя улавя началните координати и настройва системата за плъзгане.
Добавете тази функция вътре в замикването на `dragElement`, веднага след реда `terrariumElement.onpointerdown = pointerDrag;`:
```javascript
function pointerDrag(e) {
// Предотвратяване на стандартното поведение на браузъра (като селекция на текст)
e.preventDefault();
// Заснемане на началната позиция на мишката/докосването
pos3 = e.clientX; // X координата, където е започнало плъзгането
pos4 = e.clientY; // Y координата, където е започнало плъзгането
// Настройване на слушатели на събития за процеса на плъзгане
document.onpointermove = elementDrag;
document.onpointerup = stopElementDrag;
}
```
**Стъпка по стъпка, ето какво се случва:**
- **Предотвратява** настройки на браузъра, които биха попречили на плъзгането
- **Записва** точните координати, на които потребителят започва плъзгането
- **Създава** слушатели за събития за текущото движение при плъзгане
- **Подготвя** системата да следи движението на мишката/пръста по целия документ
### Разбиране на предотвратяването на събития
Редът `e.preventDefault()`е критичен за плавното плъзгане:
**Без предотвратяване браузърите могат:**
- **Да селектират** текст при плъзгане през страницата
- **Да показват** контекстни менюта при плъзгане с десен бутон
- **Да пречат** на нашето персонализирано поведение за плъзгане
- **Да създават** визуални артефакти по време на плъзгане
> 🔍 **Експеримент**: След завършване на този урок, опитайте да премахнете `e.preventDefault()` и вижте как това променя преживяването при плъзгане. Ще разберете бързо защо този ред е толкова важен!
### Система за проследяване на координатите
Свойствата `e.clientX` и `e.clientY` ни дават точни координати на мишката/докосването:
| Свойство | Какво измерва | Приложение |
|----------|---------------|------------|
| `clientX` | Хоризонтална позиция спрямо изгледа | Проследяване на движение наляво-надясно |
| `clientY` | Вертикална позиция спрямо изгледа | Проследяване на движение нагоре-надолу |
**Разбиране на тези координати:**
- **Предоставя** информация за позициониране с пикселова точност
- **Обновява се** в реално време, докато потребителят мести показалеца си
- **Остава** последователно при различни размери на екрана и нива на увеличение
- **Позволява** плавни, отзивчиви взаимодействия с плъзгане
### Настройване на слушатели на събития на ниво документ
Забележете как прикачваме събитията за движение и спиране към целия `document`, а не само към елемента на растението:
```javascript
document.onpointermove = elementDrag;
document.onpointerup = stopElementDrag;
```
**Защо ги прикачваме към документа:**
- **Продължава** проследяването дори когато мишката напусне елемента на растението
- **Предотвратява** прекъсване на плъзгането, ако потребителят се движи бързо
- **Осигурява** плавно плъзгане през целия екран
- **Обработва** краен случай, когато курсорът се премести извън прозореца на браузъра
> ⚡ **Бележка за производителността**: Ще почистим тези слушатели на събития на ниво документ, когато плъзгането спре, за да избегнем изтичане на памет и проблеми с производителността.
## Завършване на системата за плъзгане: движение и почистване
Сега ще добавим двете останали функции, които обработват действителното движение при плъзгане и почистването при спиране на плъзгането. Тези функции работят заедно, за да създадат плавно, отзивчиво движение на растението в терариума.
### Функцията elementDrag: проследяване на движението
Добавете функцията `elementDrag` веднага след затварящата къдрава скоба на `pointerDrag`:
```javascript
function elementDrag(e) {
// Изчислете изминатото разстояние от последното събитие
| `top` | Разстояние от горния ръб | Вертикално позициониране по време на влачене |
| `left` | Разстояние от левия ръб | Хоризонтално позициониране по време на влачене |
| `top` | Разстояние от горния ръб | Вертикално позициониране при плъзгане |
| `left` | Разстояние от левия ръб | Хоризонтално позициониране при плъзгане |
**Основни прозрения за свойствата offset:**
- **`offsetTop`**: Текущото разстояние от горния ръб на позиционирания родителски елемент
- **`offsetLeft`**: Текущото разстояние от левия ръб на позиционирания родителски елемент
- **Контекст на позициониране**: Тези стойности са относителни спрямо най-близкия позициониран предшественик
- **Актуализации в реално време**: Променят се незабавно, когато модифицираме CSS свойствата
**Основни наблюдения за offset свойствата:**
- **`offsetTop`**: Текущо разстояние от горния край на позиционирания родителски елемент
- **`offsetLeft`**: Текущо разстояние от левия край на позиционирания родителски елемент
- **Контекст на позициониране**: Тези стойности са относителни към най-близкия позициониран предшественик
- **Обновяване в реално време**: Променят се веднага при модифициране на CSS свойствата
> 🎯 **Философия на дизайна**: Тази система за влачене е умишлено гъвкава – няма "зони за пускане" или ограничения. Потребителите могат да поставят растенията навсякъде, като им се предоставя пълен творчески контрол върху дизайна на терариума.
> 🎯 **Философия на дизайна**: Тази система за плъзгане е умишлено гъвкава – няма „зони за пускане“ или ограничения. Потребителите могат да поставят растенията навсякъде, давайки им пълен творчески контрол над дизайна на терариума си.
## Събиране на всичко: Вашата пълна система за влачене
## Обединяване на всичко: Вашата пълна система за плъзгане
Поздравления! Току-що създадохте сложна система за влачене и пускане, използвайки чист JavaScript. Вашата пълна функция `dragElement` вече съдържа мощен closure, който управлява:
Поздравления! Току-що сте изградили сложна система за плъзгане и пускане, използвайки чист JavaScript. Вашата пълна функция `dragElement` вече съдържа мощен closure, който управлява:
**Какво постига вашият closure:**
- **Поддържа** частни променливи за позиция за всяко растение независимо
- **Управлява** целия жизнен цикъл на влаченето от начало до край
- **Осигурява** плавно и отзивчиво движение по целия екран
- **Поддържа** частни променливи с позиция за всяко растение независимо
- **Обработва** целия жизнен цикъл на плъзгане от начало до край
- **Осигурява** плавно, отзивчиво движение по целия екран
- **Почиства** ресурсите правилно, за да предотврати изтичане на памет
- **Създава** интуитивен, творчески интерфейс за дизайн на терариум
### Тестване на вашия интерактивен терариум
### Тествайте вашия интерактивен терариум
Сега тествайте вашия интерактивен терариум! Отворете файла `index.html` в уеб браузър и опитайте функционалността:
Сега тествайте вашия интерактивен терариум! Отворете вашия файл `index.html` в уеб браузър и опитайте функционалността:
1. **Кликнете и задръжте** върху някое растение, за да започнете плъзгането
2. **Преместете мишката или пръста си** и вижте как растението следва плавно
3. **Пуснете** за да оставите растението на новата позиция
4. **Експериментирайте** с различни разположения, за да изследвате интерфейса
1. **Кликнете и задръжте** върху което и да е растение, за да започнете влаченето
2. **Преместете мишката или пръста си** и наблюдавайте как растението се движи плавно
3. **Освободете**, за да пуснете растението на новата му позиция
4. **Експериментирайте** с различни подредби, за да изследвате интерфейса
🥇 **Постижение**: Създадохте пълноценна интерактивна уеб апликация, използвайки основни концепции, на които професионалните разработчици разчитат ежедневно. Тази функционалност за плъзгане и пускане използва същите принципи, които стоят зад качване на файлове, канбан дъски и много други интерактивни интерфейси.
🥇 **Постижение**: Създадохте напълно интерактивно уеб приложение, използвайки основни концепции, които професионалните разработчици използват ежедневно. Тази функционалност за влачене и пускане използва същите принципи, които стоят зад качването на файлове, канбан дъски и много други интерактивни интерфейси.
### 🔄 **Проверка на познанията**
**Пълно разбиране на системата**: Проверете овладяването си на цялата система за плъзгане:
- ✅ Как closures поддържат независимо състояние за всяко растение?
- ✅ Защо е необходима математиката при изчисляване на координатите за плавно движение?
- ✅ Какво би станало, ако забравим да почистим слушателите на събития?
- ✅ Как този модел се мащабира към по-сложни взаимодействия?
Използвайте режим Agent, за да завършите следното предизвикателство:
**Описание:** Подобрете проекта за терариум, като добавите функция за нулиране, която връща всички растения на първоначалните им позиции с плавни анимации.
**Описание:** Разширете проекта терариум с добавяне на функционалност за нулиране, която връща всички растения до първоначалните им позиции с плавни анимации.
**Подсказка:** Създайте бутон за нулиране, който при натискане анимира всички растения обратно към първоначалните им позиции в страничната лента, използвайки CSS преходи. Функцията трябва да съхранява първоначалните позиции при зареждане на страницата и плавно да премества растенията обратно към тези позиции за 1 секунда, когато бутонът за нулиране бъде натиснат.
**Подканване:** Създайте бутон за нулиране, който при клик анимира всички растения обратно до първоначалната им позиция в страничната лента, използвайки CSS трансформации. Функцията трябва да съхранява оригиналните позиции при зареждане на страницата и да анимира плавно растенията обратно към тези позиции за 1 секунда при натискане на бутона.
Научете повече за [режим Agent](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
Научете повече за [agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
## 🚀 Допълнително предизвикателство: Разширете уменията си
Готови ли сте да издигнете вашия терариум на следващо ниво? Опитайте да реализирате тези подобрения:
Готови ли сте да изведете терариума си на следващо ниво? Опитайте да реализирате тези подобрения:
**Творчески разширения:**
- **Двойно кликване** върху растение, за да го поставите отпред (манипулация на z-index)
- **Добавете визуална обратна връзка**, като леко сияние при задържане на курсора върху растенията
- **Реализирайте граници**, за да предотвратите влаченето на растения извън терариума
- **Създайте функция за запазване**, която запомня позициите на растенията, използвайки localStorage
- **Добавете звукови ефекти** при вземане и поставяне на растения
- **Двойно кликване** върху растение, за да се извиси отпред (манипулация на z-index)
- **Добавяне на визуална обратна връзка** като лек блясък при задържане върху растенията
- **Имплементиране на граници**, за да предотврати плъзгането на растения извън терариума
- **Създаване на функция за запис**, която запомня позициите на растенията с помощта на localStorage
- **Добавяне на звукови ефекти** при вдигане и поставяне на растенията
> 💡 **Възможност за учене**: Всяко от тези предизвикателства ще ви научи на нови аспекти на манипулацията на DOM, обработката на събития и дизайна на потребителския интерфейс.
> 💡 **Възможност за учене**: Всяко от тези предизвикателства ще ви научи на нови аспекти на манипулиране на DOM, работа със събития и проектиране на потребителския опит.
## Тест след лекцията
[Тест след лекцията](https://ff-quizzes.netlify.app/web/quiz/20)
## Преглед и самостоятелно обучение: Задълбочаване на разбирането
## Преглед и самостоятелно учене: Задълбочаване на разбирането
Овладяхте основите на манипулацията на DOM и closures, но винаги има още какво да се изследва! Ето някои пътища за разширяване на вашите знания и умения.
Вие овладяхте основите на манипулиране на DOM и closures, но винаги има още за научаване! Ето няколко пътеки за разширяване на вашите знания и умения.
### Алтернативни подходи за влачене и пускане
### Алтернативни подходи за плъзгане и пускане
Използвахме pointer събития за максимална гъвкавост, но уеб разработката предлага множество подходи:
Използвахме pointer събития за максимална гъвкавост, но уеб разработката предлага множество методи:
| Подход | Най-добър за | Стойност за учене |
|--------|--------------|-------------------|
| [HTML Drag and Drop API](https://developer.mozilla.org/docs/Web/API/HTML_Drag_and_Drop_API) | Качване на файлове, формални зони за влачене | Разбиране на възможностите на браузъра |
| [Touch Events](https://developer.mozilla.org/docs/Web/API/Touch_events) | Специфични взаимодействия за мобилни устройства | Мобилно-ориентирани модели за разработка |
| CSS свойства `transform` | Плавни анимации | Техники за оптимизация на производителността |
| Подход | Подходящ за | Обучителна стойност |
|--------|-------------|---------------------|
| [HTML Drag and Drop API](https://developer.mozilla.org/docs/Web/API/HTML_Drag_and_Drop_API) | Качване на файлове, формални зони за плъзгане | Разбиране на нативните възможности на браузъра |
| [Touch Events](https://developer.mozilla.org/docs/Web/API/Touch_events) | Мобилни специализирани взаимодействия | Модели на мобилна разработка |
| CSS `transform` свойства | Плавни анимации | Техники за оптимизация на производителността |
### Напреднали теми за манипулация на DOM
### Разширени теми за манипулиране на DOM
**Следващи стъпки във вашето учебно пътуване:**
- **Делегиране на събития**: Ефективно управление на събития за множество елементи
- **Intersection Observer**: Засичане, когато елементи влизат/излизат от изгледа
- **Mutation Observer**: Наблюдение за промени в структурата на DOM
- **Web Components**: Създаване на многократно използваеми, капсулирани UI елементи
- **Концепции за виртуален DOM**: Разбиране как фреймуърковете оптимизират актуализациите на DOM
**Следващи стъпки в обучението:**
- **Делегиране на събития**: Ефективно обработване на множество елементи
- **Intersection Observer**: Откриване кога елементи влизат/напускат видимата част
- **Mutation Observer**: Следене на промени в структурата на DOM
- **Уеб компоненти**: Създаване на повторно използваеми, капсулирани UI елементи
- **Концепции за виртуален DOM**: Как фреймуърковете оптимизират DOM обновяванията
### Основни ресурси за продължаващо обучение
### Основни ресурси за продължаващо учене
**Техническа документация:**
- [Ръководство за MDN Pointer Events](https://developer.mozilla.org/docs/Web/API/Pointer_events) - Изчерпателен справочник за pointer събития
- [Спецификация на W3C Pointer Events](https://www.w3.org/TR/pointerevents1/) - Официална документация за стандартите
- [Дълбоко разбиране на JavaScript Closures](https://developer.mozilla.org/docs/Web/JavaScript/Closures) - Разширени модели на closures
- [Ръководство за Pointer Events в MDN](https://developer.mozilla.org/docs/Web/API/Pointer_events) - Подробна справка за pointer събития
- [Спецификация на W3C за pointer events](https://www.w3.org/TR/pointerevents1/) - Официална стандартизирана документация
- [Дълбоко в JavaScript closures](https://developer.mozilla.org/docs/Web/JavaScript/Closures) - Разширени модели на closures
**Съвместимост с браузъри:**
- [CanIUse.com](https://caniuse.com/) - Проверете поддръжката на функции в различни браузъри
- [CanIUse.com](https://caniuse.com/) - Проверка на поддръжка на функции в браузъри
- [MDN Browser Compatibility Data](https://github.com/mdn/browser-compat-data) - Подробна информация за съвместимост
**Възможности за практика:**
- **Създайте** игра с пъзели, използвайки подобни механики за влачене
- **Създайте** канбан дъска с управление на задачи чрез влачене и пускане
- **Дизайн** на галерия с изображения с подреждане на снимки чрез влачене
- **Експериментирайте** с жестове за докосване за мобилни интерфейси
- **Създайте** пъзел игра с подобна механика на плъзгане
- **Изградете** канбан дъска с управление на задачи чрез плъзгане и пускане
- **Дизайнирайте** галерия с изображения с възможност за плъзгане на снимки
- **Експериментирайте** с докосвания за мобилни интерфейси
> 🎯 **Стратегия за учене**: Най-добрият начин да усвоите тези концепции е чрез практика. Опитвайте да създавате варианти на интерфейси с плъзгане – всеки проект ще ви научи нещо ново за взаимодействието с потребител и манипулирането на DOM.
### ⚡ **Какво можете да направите в следващите 5 минути**
- [ ] Отворете DevTools в браузъра и напишете `document.querySelector('body')` в конзолата
- [ ] Опитайте да промените текст на уебстраница чрез `innerHTML` или `textContent`
- [ ] Добавете слушател за събитие click към някой бутон или линк на уебстраница
- [ ] Изследвайте структурата на DOM дървото в панела Elements
### 🎯 **Какво можете да постигнете през този час**
- [ ] Завършете теста след урока и прегледайте концепциите за манипулиране на DOM
- [ ] Създайте интерактивна уебстраница, реагираща на кликвания на потребителя
- [ ] Практикувайте работа със събития с различни типове (click, mouseover, keypress)
- [ ] Направете прост списък със задачи или брояч чрез манипулиране на DOM
- [ ] Изследвайте връзката между HTML елементи и JavaScript обекти
### 📅 **Вашето седмично пътуване с JavaScript**
- [ ] Завършете проекта терариум с функционалност за плъзгане и пускане
- [ ] Овладейте делегиране на събития за ефективна обработка
- [ ] Научете за event loop и асинхронен JavaScript
- [ ] Практикувайте closures чрез изграждане на модули със собствено състояние
- [ ] Изучете модерни DOM API-та като Intersection Observer
- [ ] Създавайте интерактивни компоненти без използване на фреймуъркове
- [ ] Научете модерен фреймуърк (React, Vue или Angular) и го сравнете с ванилия DOM
- [ ] Допринасяйте в отворени JavaScript проекти
- [ ] Усвоете напреднали концепции като уеб компоненти и потребителски елементи
- [ ] Изграждайте високопроизводителни уеб приложения с оптимални DOM модели
- [ ] Преподавайте на други за манипулиране на DOM и JavaScript основи
## 🎯 Вашата времева линия за овладяване на JavaScript DOM
```mermaid
timeline
title Напредък в усвояването на DOM & JavaScript
section Основи (15 минути)
Разбиране на DOM: Методи за подбор на елементи
: Навигация в дървовидна структура
: Шаблони за достъп до свойства
section Обработка на събития (20 минути)
Взаимодействие с потребителя: Основи на събитията със стрелец
: Настройка на слушатели на събития
: Съвместимост между устройства
: Техники за предотвратяване на събития
section Затваряния (25 минути)
Управление на обхвата: Създаване на частни променливи
: Устойчивост на функции
: Шаблони за управление на състоянието
: Ефективност на паметта
section Система за плъзгане (30 минути)
Интерактивни функции: Проследяване на координати
: Изчисляване на позиция
: Математика на движението
: Процедури за почистване
section Разширени шаблони (45 минути)
Професионални умения: Делегиране на събития
: Оптимизация на производителността
: Обработка на грешки
: Съображения за достъпност
section Разбиране на фреймуърк (1 седмица)
Модерна разработка: Концепции за виртуален DOM
: Библиотеки за управление на състоянието
: Архитектури на компоненти
: Интеграция с инструменти за компилиране
section Експертно ниво (1 месец)
Разширени DOM API-та: Intersection Observer
: Mutation Observer
: Потребителски елементи
: Уеб компоненти
```
### 🛠️ Обобщение на вашия JavaScript инструментарий
След приключване на този урок вие вече имате:
- **Владеене на DOM**: Избор на елементи, манипулиране на свойства и навигация в дървото
- **Експертиза в събитията**: Обработка на взаимодействия на различни устройства с pointer събития
- **Разбиране на closures**: Управление на частно състояние и продължителност на функциите
- **Интерактивни системи**: Пълна имплементация на drag-and-drop от нулата
- **Осъзнатост за производителността**: Правилно почистване на събития и управление на паметта
- **Модерни модели**: Техники за организиране на код, използвани в професионална разработка
- **Потребителско изживяване**: Създаване на интуитивни, отзивчиви интерфейси
**Професионални умения, които сте придобили**: Създавали сте функционалности с използване на същите техники като:
- **Trello/Kanban дъски**: Плъзгане на карти между колони
- **Системи за качване на файлове**: Обработка на файлове чрез плъзгане и пускане
- **Галерии с изображения**: Интерфейси за подреждане на снимки
- **Мобилни приложения**: Интеракции, базирани на докосване
> 🎯 **Стратегия за учене**: Най-добрият начин да затвърдите тези концепции е чрез практика. Опитайте да създадете вариации на интерфейси с влачене – всеки проект ще ви научи на нещо ново за взаимодействието с потребителя и манипулацията на DOM.
**Следващо ниво**: Готови сте да изследвате модерни фреймуъркове като React, Vue или Angular, които се основават на тези фундаментални концепции за манипулиране на DOM!
## Задача
@ -361,5 +765,7 @@ function stopElementDrag() {
---
**Отказ от отговорност**:
Този документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Не носим отговорност за недоразумения или погрешни интерпретации, произтичащи от използването на този превод.
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Отказ от отговорност**:
Този документ е преведен с помощта на AI преводаческа услуга [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи могат да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за каквито и да е недоразумения или неправилни тълкувания, възникнали от използването на този превод.
# Моето терариумче: Проект за изучаване на HTML, CSS и манипулация на DOM с JavaScript 🌵🌱
## Разгръщане на вашия Terrarium
Малка медитация с плъзгане и пускане на код. С малко HTML, JS и CSS ще можете да създадете уеб интерфейс, да го стилизирате и дори да добавите множество интеракции по ваш избор.
Можете да разположите или публикувате своя Terrarium в уебс помощта на **Azure Static Web Apps**.
1. [Въведение в HTML](./1-intro-to-html/README.md)
2. [Въведение в CSS](./2-intro-to-css/README.md)
3. [Въведение в DOM и затваряния в JS](./3-intro-to-DOM-and-closures/README.md)
[](https://portal.azure.com/#create/Microsoft.StaticApp)
## Кредити
Написано с ♥️ от [Jen Looper](https://www.twitter.com/jenlooper)
Терариумът, създаден чрез CSS, е вдъхновен от стъкления буркан на Jakub Mandra [codepen](https://codepen.io/Rotarepmi/pen/rjpNZY).
Илюстрациите са ръчно нарисувани от [Jen Looper](http://jenlooper.com) с помощта на Procreate.
## Публикувайте вашето терариумче
Можете да публикувате вашето терариумче в интернет, използвайки Azure Static Web Apps.
1. Направете fork на това хранилище
2. Натиснете този бутон
[](https://portal.azure.com/?feature.customportal=false&WT.mc_id=academic-77807-sagibbon#create/Microsoft.StaticApp)
3. Следвайте стъпките в съветника за създаване на вашето приложение. Уверете се, че сте задали корена на приложението да бъде или `/solution`, или коренът на вашата кодова база. В това приложение няма API, така че не се притеснявайте да добавяте такова. Във вашето fork-нато хранилище ще бъде създадена папка за GitHub, която ще помогне на услугите за изграждане на Azure Static Web Apps да изградят и публикуват вашето приложение на нов URL адрес.
3. Следвайте съветника за настройка, за да създадете вашето приложение.
- Задайте **App root** на `/solution` или на корена на вашата кодова база.
- В това приложение няма API, така че можете да пропуснете конфигурацията на API.
- Папка `.github` ще бъде създадена автоматично, за да помогне на Azure Static Web Apps да изгражда и публикува вашето приложение.
---
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Отказ от отговорност**:
Този документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматичните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия изходен език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.
Този документ е преведен с помощта на AI преводаческа услуга [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за каквито и да е недоразумения или неправилни тълкувания, произтичащи от използването на този превод.
# Програмиране, базирано на събития - Създайте игра за писане
# Програмиране, основано на събития - Създайте игра за писане
```mermaid
journey
title Вашето пътешествие в разработването на игра за писане
section Основи
Планиране на структурата на играта: 3: Student
Дизайн на потребителския интерфейс: 4: Student
Настройка на HTML елементи: 4: Student
section Функционалност
Обработка на потребителски вход: 4: Student
Следене на времето: 5: Student
Изчисляване на точността: 5: Student
section Характеристики
Добавяне на визуална обратна връзка: 5: Student
Реализиране на игрова логика: 5: Student
Изглаждане на преживяването: 5: Student
```
## Въведение
Ето нещо, което всеки разработчик знае, но рядко говори за него: бързото писане е суперсила! 🚀 Помислете - колкото по-бързо можете да прехвърлите идеите си от мозъка към редактора на код, толкова повече вашата креативност може да се разгърне. Това е като директен канал между мислите ви и екрана.
Ето нещо, което всеки разработчик знае, но рядко говори за него: бързото писане е суперсила! 🚀 Помислете - колкото по-бързо можете да прехвърлите идеите си от мозъка си към кода, толкова повече може да тече вашата креативност. Това е като да имате директен канал между мислите си и екрана.
Искате ли да научите един от най-добрите начини да подобрите това умение? Познахте - ще създадем игра!
```mermaid
pie title Характеристики на играта
"Обратна връзка в реално време" : 25
"Проследяване на представянето" : 20
"Интерактивен потребителски интерфейс" : 20
"Система за таймер" : 15
"Управление на цитати" : 10
"Показване на резултатите" : 10
```
Искате ли да знаете един от най-добрите начини да подобрите този умение? Познахте - ще създадем игра!
```mermaid
flowchart LR
A[Играчът стартира игра] --> B[Показва се случаен цитат]
B --> C[Играчът въвежда символи]
C --> D{Символът е правилен?}
D -->|Да| E[Зелен акцент]
D -->|Не| F[Червен акцент]
E --> G[Актуализиране на точността]
F --> G
G --> H{Цитатът е завършен?}
H -->|Не| C
H -->|Да| I[Изчисляване на WPM]
I --> J[Показване на резултатите]
J --> K[Игра отново?]
K -->|Да| B
K -->|Не| L[Край на играта]
style A fill:#e1f5fe
style D fill:#fff3e0
style E fill:#e8f5e8
style F fill:#ffebee
style I fill:#f3e5f5
```
> Нека създадем страхотна игра за писане заедно!
Готови ли сте да приложите всички тези умения по JavaScript, HTML и CSS, които сте научили? Ще създадем игра за писане, която ще ви предизвика с произволни цитати от легендарния детектив [Шерлок Холмс](https://en.wikipedia.org/wiki/Sherlock_Holmes). Играта ще следи колко бързо и точно можете да пишете - и повярвайте ми, тя е по-завладяваща, отколкото си мислите!
Готови ли сте да използвате всички тези умения по JavaScript, HTML и CSS, които сте усвоили? Ще създадем игра за писане, която ще ви предизвика с произволни цитати от легендарния детектив [Шерлок Холмс](https://en.wikipedia.org/wiki/Sherlock_Holmes). Играта ще следи колко бързо и точно можете да пишете – повярвайте ми, това е по-заразно, отколкото си мислите!

```mermaid
mindmap
root((Разработка на игра за писане))
User Interface
Input Elements
Visual Feedback
Responsive Design
Accessibility
Game Logic
Quote Selection
Timer Management
Accuracy Tracking
Score Calculation
Event Handling
Keyboard Input
Button Clicks
Real-time Updates
Game State Changes
Performance Metrics
Words Per Minute
Character Accuracy
Error Tracking
Progress Display
User Experience
Immediate Feedback
Clear Instructions
Engaging Content
Achievement System
```

## Какво трябва да знаете
## Какво ще трябва да знаете
Преди да се потопим, уверете се, че сте запознати с тези концепции (не се притеснявайте, ако имате нужда от кратко опресняване - всички сме били там!):
```mermaid
flowchart TD
A[Действие на потребителя] --> B{Тип на събитието?}
B -->|Натискане на клавиш| C[Клавиатурно събитие]
B -->|Щракване на бутон| D[Мишено събитие]
B -->|Таймер| E[Събитие време]
C --> F[Провери символа]
D --> G[Стартирай/Ресетвай игра]
E --> H[Обнови таймера]
F --> I{Правилно?}
I -->|Да| J[Освети в зелено]
I -->|Не| K[Освети в червено]
J --> L[Обнови резултат]
K --> L
L --> M[Провери състоянието на играта]
G --> N[Генерирай нов цитат]
H --> O[Покажи време]
M --> P{Играта завършена?}
P -->|Да| Q[Покажи резултатите]
P -->|Не| R[Продължи играта]
style A fill:#e1f5fe
style F fill:#e8f5e8
style I fill:#fff3e0
style Q fill:#f3e5f5
```
Преди да започнем, уверете се, че сте запознати с тези концепции (не се притеснявайте, ако имате нужда от бързо припомняне - всички сме били там!):
- Създаване на текстови полета за въвеждане и бутони
- Създаване на текстови полета и бутони
- CSS и задаване на стилове чрез класове
- Основи на JavaScript
- Създаване на масив
- Създаване на случайно число
- Получаване на текущото време
Ако някои от тези неща ви се струват малко забравени, това е напълно нормално! Понякога най-добрият начин да затвърдите знанията си е като се впуснете в проект и разберете нещата в процеса.
Ако някое от тези неща ви се струва малко заръждясало, нищо страшно! Понякога най-добрият начин да затвърдите знанията си е като започнете проект и разберете всичко в движение.
## Да го направим!
### 🔄 **Образователна проверка**
**Оценка на основите**: Преди да започнете разработката, уверете се, че разбирате:
- ✅ Как работят HTML формите и елементите за въвеждане
- ✅ CSS класове и динамично стилизиране
- ✅ JavaScript слушатели и обработващи функции за събития
- ✅ Манипулиране на масиви и случайно избиране
- ✅ Измерване на време и изчисления
[Създаване на игра за писане чрез програмиране, базирано на събития](./typing-game/README.md)
**Бърз самотест**: Можете ли да обясните как тези концепции работят заедно в интерактивна игра?
- **Събития** се задействат, когато потребителите взаимодействат с елементи
- **Обработващи функции** обработват тези събития и актуализират състоянието на играта
- **CSS** осигурява визуална обратна връзка за действията на потребителя
- **Измерването на време** позволява измерване на представяне и напредък в играта
## Кредити
```mermaid
quadrantChart
title Развитие на уменията за игра с писане
x-axis Начинаещ --> Експерт
y-axis Статичен --> Интерактивен
quadrant-1 Напреднали игри
quadrant-2 Приложения в реално време
quadrant-3 Основни страници
quadrant-4 Интерактивни сайтове
HTML Forms: [0.3, 0.2]
CSS Styling: [0.4, 0.3]
Event Handling: [0.7, 0.8]
Game Logic: [0.8, 0.9]
Performance Tracking: [0.9, 0.7]
```
## Нека построим това!
Написано с ♥️ от [Кристофър Харисън](http://www.twitter.com/geektrainer)
[Създаване на игра за писане чрез програмиране, основано на събития](./typing-game/README.md)
### ⚡ **Какво можете да направите през следващите 5 минути**
- [ ] Отворете конзолата на браузъра и опитайте да слушате за клавишни събития с`addEventListener`
- [ ] Създайте проста HTML страница с полe за въвеждане и тествайте засичане на писане
- [ ] Упражнявайте манипулиране на текст, като сравнявате написания текст с целевия
- [ ] Експериментирайте с`setTimeout`, за да разберете как работят таймерите
### 🎯 **Какво можете да постигнете този час**
- [ ] Завършете викторината след урока и разберете програмиране, основано на събития
- [ ] Изградете основна версия на играта за писане с проверка на думи
- [ ] Добавете визуална обратна връзка за правилно и неправилно писане
- [ ] Прилагайте проста система за оценяване на базата на скорост и точност
- [ ] Стилизирайте играта с CSS, за да я направите визуално привлекателна
### 📅 **Вашето седмично разработване на игра**
- [ ] Завършете пълната игра за писане с всички функции и полиран вид
- [ ] Добавете нива на трудност с различна сложност на думите
- [ ] Прилагайте проследяване на статистики на потребителя (думи в минута, точност с времето)
- [ ] Създайте звукови ефекти и анимации за по-добро потребителско преживяване
- [ ] Направете играта си адаптивна за мобилни устройства с тъч интерфейс
- [ ] Споделете играта си онлайн и съберете обратна връзка от потребители
### 🌟 **Вашето месечно интерактивно развитие**
- [ ] Създавайте множество игри, изследващи различни модели на взаимодействие
- [ ] Научете за игрови цикли, управление на състояния и оптимизация на производителността
- [ ] Допринасяйте за проекти с отворен код в разработката на игри
- [ ] Овладейте напреднали концепции за време и плавни анимации
- [ ] Наставлявайте други, заинтересовани от разработката на игри и потребителско взаимодействие
## 🎯 Вашата времева линия за овладяване на игра за писане
```mermaid
timeline
title Прогрес в усвояването на разработка на игри
section Настройка (10 минути)
Project Structure: HTML основа
: CSS стилизиране
: Създаване на JavaScript файл
section Потребителски интерфейс (20 минути)
Interactive Elements: Полета за въвеждане
: Бутони
: Зони за показване
: Адаптивен дизайн
section Обработка на събития (25 минути)
User Interaction: Събития от клавиатура
: Събития с мишка
: Обратна връзка в реално време
: Управление на състоянието
section Игрова логика (30 минути)
Core Functionality: Генериране на цитати
: Сравнение на символи
: Изчисляване на точност
: Имплементация на таймер
section Проследяване на производителността (35 минути)
Metrics & Analytics: Изчисляване на WPM
: Проследяване на грешки
: Визуализация на напредъка
: Показване на резултати
section Финални щрихи и подобрения (45 минути)
User Experience: Визуална обратна връзка
: Звукови ефекти
: Анимации
: Функции за достъпност
section Разширени функции (1 седмица)
Extended Functionality: Нива на трудност
: Таблици с класиране
: Персонализирани цитати
: Опции за мултиплейър
section Професионални умения (1 месец)
Game Development: Оптимизация на производителността
: Архитектура на кода
: Стратегии за тестване
: Шаблони за разгръщане
```
### 🛠️ Резюме на вашите инструменти за разработка на игри
След завършване на този проект ще сте овладели:
- **Програмиране, основано на събития**: Отзивчиви потребителски интерфейси, които реагират на вход
- **Обратна връзка в реално време**: Незабавни визуални и представителни актуализации
- **Измерване на производителността**: Точни системи за измерване на време и точкуване
- **Управление на състоянието на играта**: Контрол на потока на приложението и потребителското преживяване
- **Интерактивен дизайн**: Създаване на ангажиращи, пристрастяващи потребителски преживявания
- **Модерни уеб API-та**: Използване на възможностите на браузъра за богати взаимодействия
- **Патерни за достъпност**: Приобщаващ дизайн за всички потребители
**Приложения в реалния свят**: Тези умения се прилагат директно в:
- **Уеб приложения**: Всеки интерактивен интерфейс или табло за управление
- **Образователен софтуер**: Платформи за обучение и инструменти за оценка на умения
- **Продуктивни инструменти**: Текстови редактори, IDE-та и софтуер за съвместна работа
- **Индустрията на игрите**: Игри в браузъра и интерактивни забавления
- **Мобилна разработка**: Тъч-базирани интерфейси и обработка на жестове
**Следващо ниво**: Готови сте да изследвате напреднали игрови рамки, системи за мултиплейър в реално време или сложни интерактивни приложения!
## Благодарности
Написано с ♥️ от [Christopher Harrison](http://www.twitter.com/geektrainer)
---
**Отказ от отговорност**:
Този документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Отказ от отговорност**:
Този документ е преведен с помощта на AI преводаческа услуга [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стараем да осигурим точност, имайте предвид, че автоматизираните преводи могат да съдържат грешки или неточности. Оригиналният документ на неговия първоначален език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за никакви недоразумения или неправилни тълкувания, произтичащи от използването на този превод.
Чудили ли сте се някога как уебсайтовете разбират, когато кликнете върху бутон или въведете текст в текстово поле? Това е магията на програмирането, базирано на събития! Какъв по-добър начин да научите това основно умение от това да създадете нещо полезно - игра за скорост на писане, която реагира на всяко натискане на клавиш.
Замисляли ли сте се някога как сайтовете разбират кога кликнете върху бутон или напишете нещо в текстово поле? Това е магията на събитийно ориентираното програмиране! Какъв по-добър начин да научите този важен умение, от това да създадете нещо полезно - игра за бързина на писане, която реагира на всеки натиснат клавиш.
Ще видите от първа ръка как уеб браузърите "говорят" с вашия JavaScript код. Всеки път, когато кликнете, пишете или движите мишката, браузърът изпраща малки съобщения (наричаме ги събития) към вашия код, а вие решавате как да реагирате!
Ще видите на живо как уеб браузърите "комуникират" с вашия JavaScript код. Всеки път, когато кликнете, напишете или преместите мишката, браузърът изпраща малки съобщения (наричаме ги събития) към вашия код и вие решавате как да отговорите!
Когато приключим, ще сте създали истинска игра за писане, която следи вашата скорост и точност. Още по-важно е, че ще разберете основните концепции, които задвижват всеки интерактивен уебсайт, който някога сте използвали. Да започваме!
Когато приключим тук, ще сте създали истинска игра за писане, която проследява скоростта и точността ви. Още по-важното е, че ще разберете фундаменталните концепции, които задвижват всеки интерактивен уеб сайт, който някога сте ползвали. Хайде да започваме!
## Тест преди лекцията
## Предварителен тест пред лекцията
[Тест преди лекцията](https://ff-quizzes.netlify.app/web/quiz/21)
[Предварителен тест пред лекцията](https://ff-quizzes.netlify.app/web/quiz/21)
## Програмиране, базирано на събития
## Програмиране, ориентирано към събития
Помислете за любимото си приложение или уебсайт - какво го прави живо и отзивчиво? Всичко е свързано с това как реагира на вашите действия! Всеки натиск, клик, плъзгане или натискане на клавиш създава това, което наричаме "събитие", и именно тамсе случва истинската магия на уеб разработката.
Помислете за любимото си приложение или сайт - какво го кара да се чувства жив и отзивчив? Всичко е в това как реагира на вашите действия! Всеки клик, докосване, плъзгане или натискане на клавиш създава нещо, което наричаме "събитие", и туксе случва истинската магия на уеб разработката.
Ето какво прави програмирането за уеб толкова интересно: никога не знаем кога някой ще кликне върху този бутон или ще започне да пише в текстово поле. Може да кликне веднага, да изчака пет минути или изобщо да не кликне! Тази непредсказуемост означава, че трябва да мислим по различен начин за това как пишем нашия код.
Ето какво прави програмирането за уеб толкова интересно: никога не знаем кога някой ще кликне бутона или ще започне да пише в текстовото поле. Може да кликне веднага, да изчака пет минути или може никога да не кликне! Тази непредсказуемост ни кара да мислим по различен начин как да пишем кода си.
Вместо да пишем код, който се изпълнява отгоре надолу като рецепта, пишем код, който търпеливо чака нещо да се случи. Това е подобно на начина, по който телеграфните оператори през 1800-те години са седели до своите машини, готови да реагират в момента, в който съобщение премине през жицата.
Вместо да пишем код, който се изпълнява отгоре надолу като рецепта, ние пишем код, който търпеливо чака нещо да се случи. Това е подобно на начина, по който телеграфните оператори през 1800-те сядат до машините си, готови да реагират веднага щом през жицата премине съобщение.
И така, какво точное "събитие"? Просто казано, това е нещо, което се случва! Когато кликнете върху бутон - това е събитие. Когато напишете буква - това е събитие. Когато движите мишката - това е друго събитие.
Какво всъщносте "събитие"? Просто казано, това е нещо, което се случва! Когато кликнете върху бутон - това е събитие. Когато натиснете клавиш - това е събитие. Когато преместите мишката - това е друго събитие.
Програмирането, базирано на събития, ни позволява да настроим нашия код да слуша и да реагира. Създаваме специални функции, наречени **слушатели на събития**, които търпеливо чакат определени неща да се случат, а след това действат, когато това стане.
Програмирането, ориентирано към събития, ни позволява да настроим кода си да слуша и реагира. Създаваме специални функции, наречени **слушатели на събития** (event listeners), които търпеливо чакат специфични неща да се случат и веднага се задействат, когато това стане.
Представете си слушателите на събития като звънец за вашия код. Настройвате звънеца (`addEventListener()`), казвате му какъв звук да слуша (като 'click' или 'keypress') и след това определяте какво трябва да се случи, когато някой го натисне (вашата персонализирана функция).
Мислете за слушателите на събития като звънец за вашия код. Вие настройвате звънеца (`addEventListener()`), казвате му за какъв звук да слуша (например 'click' или 'keypress'), и след това посочвате какво да се случи, когато някой звънне (вашата персонализирана функция).
**Ето как работят слушателите на събития:**
- **Слушат** за специфични действия на потребителя като кликвания, натискания на клавиши или движения на мишката
- **Изпълняват** вашия персонализиран код, когато се случи определеното събитие
- **Реагират** незабавно на взаимодействията на потребителя, създавайки безпроблемно изживяване
- **Обработват** множество събития върху един и същ елемент, използвайки различни слушатели
- **Слушат** за специфични действия на потребителя като кликове, натискане на клавиши или движение на мишката
- **Изпълняват** вашия код веднага, когато настъпи посоченото събитие
- **Реагират** мигновено на действията на потребителя, създавайки плавно преживяване
- **Обработват** множество събития на един и същ елемент чрез различни слушатели
> **NOTE:** Струва си да се подчертае, че има множество начини за създаване на слушатели на събития. Можете да използвате анонимни функции или да създадете именувани. Можете да използвате различни преки пътища, като задаване на свойството `click` или използване на`addEventListener()`. В нашето упражнение ще се фокусираме върху `addEventListener()` и анонимни функции, тъй като това вероятно енай-често използваната техника от уеб разработчиците. Освен това е най-гъвкавата, тъй като `addEventListener()` работи за всички събития, а името на събитието може да бъде предоставено като параметър.
> **ЗАБЕЛЕЖКА:** Струва си да се отбележи, че има много начини за създаване на слушатели на събития. Можете да използвате анонимни функции или да създадете именувани. Можете да използвате разнообразни кратки начини като настройване на свойството `click` или чрез`addEventListener()`. В нашето упражнение ще се фокусираме върху `addEventListener()` и анонимни функции, тъй като това евероятно най-често използваната техника от уеб разработчиците. Освен това е най-гъвкавата, защото `addEventListener()` работи с всички събития и името на събитието може да се подаде като параметър.
### Често срещани събития
### Често използвани събития
Докатоуеб браузърите предлагат десетки различни събития, които можете да слушате, повечето интерактивни приложения разчитат само на няколко основни събития. Разбирането на тези основни събития ще ви даде основа за изграждане на сложни взаимодействия с потребителите.
Въпреки чеуеб браузърите предлагат десетки различни събития, на които можете да слушате, повечето интерактивни приложения разчитат само на няколко основни. Разбирането на тези основни събития ще ви даде основата за изграждане на по-сложни взаимодействия с потребителите.
Има [десетки събития](https://developer.mozilla.org/docs/Web/Events), които можете да слушате, когато създавате приложение. По същество всичко, което потребителят прави на страницата, предизвиква събитие, което ви дава много сила да гарантирате, че те получават желаното изживяване. За щастие, обикновено ще ви трябват само няколко основни събития. Ето някои често срещани (включително двете, които ще използваме при създаването на нашата игра):
Има [десетки събития](https://developer.mozilla.org/docs/Web/Events), към които можете да се прикачите при създаването на приложение. Почти всичко, което потребителят прави на страница, повдига събитие, което ви дава голяма възможност да осигурите нужния опит. За щастие, обикновено ви трябват само няколко събития. Ето някои често използвани (включително тези, които ще ползваме в нашата игра):
| Събитие | Описание | Чести случаи на употреба |
|---------|----------|--------------------------|
| Събитие | Описание | Често използвани случаи |
|---------|----------|------------------------|
| `click` | Потребителят кликна върху нещо | Бутони, линкове, интерактивни елементи |
| `contextmenu` | Потребителят кликна с десния бутон на мишката | Персонализирани контекстни менюта |
| `select` | Потребителят маркира текст | Редактиране на текст, операции за копиране |
| `input` | Потребителят въведе текст | Валидация на формуляри, търсене в реално време |
| `contextmenu` | Потребителят кликна с десен бутон на мишката | Персонализирани менюта с десен бутон |
| `select` | Потребителят избра текст | Редактиране на текст, копиране |
| `input` | Потребителят въведе текст | Валидация на форми, търсене в реално време |
**Разбиране на тези типове събития:**
- **Активират се**, когато потребителите взаимодействат със специфични елементи на вашата страница
- **Предоставят** подробна информация за действието на потребителя чрез обекти на събития
- **Позволяват** създаването на отзивчиви, интерактивни уеб приложения
- **Работят** последователно на различни браузъри и устройства
- **Се задействат**, когато потребителите взаимодействат със специфични елементи на страницата
- **Осигуряват** подробна информация за действието на потребителя чрез обекти на събитието
- **Позволяват** създаването на отзивчиви и интерактивни уеб приложения
- **Работят** постоянно на различни браузъри и устройства
## Създаване на играта
Сега, когато разбирате как работят събитията, нека приложим това знание на практика, като създадем нещо полезно. Ще създадем игра за скорост на писане, която демонстрира обработката на събития, докато ви помага да развиете важно умение за разработчици.
Сега, когато разбирате как работят събитията, нека приложим това знание като създадем нещо полезно. Ще направим игра за скорост на писане, която демонстрира обработката на събития и помага да развиете важни умения за разработчици.
Ще създадем игра, за да изследваме как работят събитията в JavaScript. Нашата игра ще тества умението на играча за писане, което е едно от най-недооценените умения, които всички разработчици трябва да имат. Забавен факт: клавиатурната подредба QWERTY, която използваме днес, всъщност е проектирана през 1870-те години за пишещи машини - и добрите умения за писане все още са толкова ценни за програмистите днес! Общият ход на играта ще изглежда така:
Ще създадем игра, за да изследваме как работят събитията в JavaScript. Наша игра ще тества умението за писане на играча – една от най-пренебрегваните способности, които всеки разработчик трябва да притежава. Забавен факт: клавиатурната подредба QWERTY, която използваме днес, всъщност е проектирана през 1870-те за пишещи машини – и добрите умения за писане са също толкова ценни и за програмистите днес! Общият ход на играта ще изглежда така:
A[Играчът натиска Старт] --> B[Показва се случаен цитат]
B --> C[Играчът пише в текстовото поле]
C --> D{Дума завършена?}
D -->|Да| E[Издели следващата дума]
D -->|Не| F{Досега правилно?}
F -->|Да| G[Запази нормалния стил]
F -->|Не| H[Покажи стила за грешка]
E --> I{Цитатът завършен?}
I -->|Не| C
I -->|Да| J[Покажи съобщение за успех с време]
G --> C
H --> C
```
**Ето как ще работи нашата игра:**
- **Започва**, когато играчът кликне върху бутона за старт и се показва случайна цитата
- **Проследява** напредъка на играча при писане дума по дума в реално време
- **Започва** когато играчът натисне бутона за старт и показва произволен цитат
- **Проследява** напредъка на писане на играча дума по дума в реално време
- **Подчертава** текущата дума, за да насочи фокуса на играча
- **Осигурява** незабавна визуална обратна връзка за грешки при писане
- **Изчислява** и показва общото време, когато цитатът е завършен
- **Осигурява** незабавна визуална обратна връзка при грешки в писането
- **Изчислява** и показва общото време след завършване на цитата
Нека изградим нашата игра и да научим за събитията!
Нека създадем играта си и научим повече за събитията!
### Структура на файловете
Преди да започнем да кодираме, нека се организираме! Да имате чиста структура на файловете от самото начало ще ви спести главоболия по-късно и ще направи вашия проект по-професионален. 😊
Преди да започнем да пишем код, нека се организираме! Имате ли чиста структура на файловете от самото начало, това ще ви спести главоболия по-късно и ще направи проекта ви по-професионален. 😊
Ще запазим нещата прости с само три файла: `index.html` за структурата на страницата, `script.js` за цялата логика на играта и `style.css`, за да направим всичко да изглежда страхотно. Това е класическото трио, което задвижва повечето уебсайтове!
Ще поддържаме нещата прости с три файла: `index.html` за структурата на страницата, `script.js` за логиката на играта и `style.css` за оформлението. Това е класическото трио, което движи почти целия уеб!
**Създайте нова папка за вашата работа, като отворите конзола или терминал и изпълните следната команда:**
**Създайте нова папка за работата си, като отворите конзола или терминал и изпълните следната команда:**
```bash
# Linux or macOS
# Linux или macOS
mkdir typing-game && cd typing-game
# Windows
@ -108,9 +107,9 @@ md typing-game && cd typing-game
```
**Ето какво правят тези команди:**
- **Създават** нова директория, наречена `typing-game`, за вашите проектни файлове
- **Навигират** автоматично в новосъздадената директория
- **Настройват** чисто работно пространство за разработка на вашата игра
- **Създават** нова директория, наречена `typing-game` за файловете на проекта
- **Влизат** автоматично в новосъздадената директория
- **Настройват** чисто работно пространство за разработка на играта
**Отворете Visual Studio Code:**
@ -120,34 +119,34 @@ code .
**Тази команда:**
- **Стартира** Visual Studio Code в текущата директория
- **Отваря** вашата проектна папка в редактора
- **Осигурява** достъп до всички инструменти за разработка, които ще ви трябват
- **Отваря** папката на проекта в редактора
- **Дава** достъп до всички инструменти за разработка, от които ще имате нужда
**Добавете три файла към папката във Visual Studio Code със следните имена:**
- `index.html` - Съдържа структурата и съдържанието на вашата игра
- `script.js` - Обработва цялата логика на играта и слушателите на събития
- `style.css` - Определя визуалния вид и стилизацията
**Добавете три файла в папката в Visual Studio Code със следните имена:**
- `index.html` - Съдържа структурата и съдържанието на играта
- `script.js` - Обработва логиката и слушателите на събития за играта
- `style.css` - Определя визуалното оформление и стила
## Създаване на потребителския интерфейс
Сега нека изградим сцената, където ще се случи цялото действие на нашата игра! Помислете за това като за проектиране на контролен панел за космически кораб - трябва да се уверим, че всичко, от което играчите нисе нуждаят, е точно там, където го очакват.
Сега нека построим сцената, на която ще се случва цялото действие в играта! Представете си го като проектиране на контролен панел за космически кораб – трябва да сме сигурни, че всичко, от което играчите се нуждаят, е точно там, където го очакват.
Нека разберем какво всъщност ни трябва за нашата игра. Ако играете игра за писане, какво бихте искали да видите на екрана? Ето какво ще ни трябва:
Да разберем от какво всъщност се нуждае нашата игра. Ако играехте игра за писане, какво бихте искали да виждате на екрана? Ето какво ще ни трябва:
| Елемент на интерфейса | Цел | HTML елемент |
|------------------------|-----|--------------|
| UI елемент | Цел | HTML елемент |
|------------|-----|--------------|
| Показване на цитат | Показва текста за писане | `<p>`с`id="quote"` |
| Зона за съобщения | Показва статус и съобщения за успех | `<p>`с`id="message"` |
| Област за съобщения | Показва статус и съобщения за успех | `<p>`с`id="message"` |
| Текстово поле | Където играчите пишат цитата | `<input>`с`id="typed-value"` |
| Бутон за старт | Започва играта | `<button>`с`id="start"` |
| Бутон старт | Започва играта | `<button>`с`id="start"` |
- **Присвоява** уникални идентификатори на елементите за презаписване с JavaScript
- **Осигурява** ясна визуална йерархия за по-добър потребителски опит
- **Включва** семантични HTML елементи за достъпност
Всеки от тези елементи ще се нуждае от ID, за да можем да работим с тях в нашия JavaScript. Ще добавим и препратки към CSS и JavaScript файловете, които ще създадем.
Всеки от тези елементи ще трябва да има ID, за да можем да работим с тях в JavaScript. Ще добавим и препратки към CSS и JavaScript файловете, които ще създадем.
Създайте нов файл с име `index.html`. Добавете следния HTML:
@ -172,52 +171,52 @@ code .
</html>
```
**Разбивка на това, което постига тази HTML структура:**
- **Свързва** CSS стиловия файл в `<head>` за стилизация
- **Създава** ясен заглавие и инструкции за потребителите
- **Установява** резервни параграфи със специфични ID-та за динамично съдържание
**Разграждане на това, което постига тази HTML структура:**
- **Свързва** CSS стиловата таблица в `<head>` за оформление
- **Създава** ясен заглавен текст и инструкции за потребителя
- **Установява** празни параграфи с конкретни идентификатори за динамично съдържание
- **Включва** текстово поле с атрибути за достъпност
- **Осигурява** бутон за старт, който да задейства играта
- **Зарежда** JavaScript файла в края за оптимална производителност
- **Предоставя** бутон за старт на играта
- **Зарежда** JavaScript файла в края за оптимална работа
### Стартиране на приложението
Тестването на вашето приложение често по време на разработка ви помага да откривате проблеми рано и да виждате напредъка си в реално време. Live Server е безценен инструмент, който автоматично обновява вашия браузър, когато запазите промените, правейки разработката много по-ефективна.
Честото тестване на приложението по време на разработка ви помага да откривате проблеми рано и да виждате напредъка си в реално време. Live Server е безценен инструмент, който автоматично презарежда браузъра при всяко записване на промени, което прави разработката много по-ефективна.
Винаги е най-добре да разработвате итеративно, за да видите как изглеждат нещата. Нека стартираме нашето приложение. Има чудесно разширение за Visual Studio Code, наречено [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer&WT.mc_id=academic-77807-sagibbon), което ще хоства вашето приложение локално и ще обновява браузъра всеки път, когато запазите.
Най-добре е да разработвате итеративно, за да виждате как изглеждат нещата. Нека стартираме приложението. Съществува страхотно разширение за Visual Studio Code, наречено [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer&WT.mc_id=academic-77807-sagibbon), което ще хоства локално приложението ви и ще обновява браузъра всеки път, когато запишете.
**Инсталирайте [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer&WT.mc_id=academic-77807-sagibbon), като следвате линка и кликнете върху Install:**
**Инсталирайте [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer&WT.mc_id=academic-77807-sagibbon), като следвате връзката и натиснете Инсталирай:**
**Ето какво се случва по време на инсталацията:**
- **Подканва** вашия браузър да отвори Visual Studio Code
- **Насочва** ви през процеса на инсталиране на разширението
- **Може да изисква** рестартиране на Visual Studio Code за завършване на настройката
**По време на инсталацията:**
- **Подканя** браузъра да отвори Visual Studio Code
- **Ви води** през процеса на инсталиране на разширението
- **Може да изисква** рестартиране на Visual Studio Code, за да завърши настройката
**След като е инсталиран, във Visual Studio Code натиснете Ctrl-Shift-P (или Cmd-Shift-P), за да отворите командния палет:**
**След като е инсталирано, в Visual Studio Code натиснете Ctrl-Shift-P (или Cmd-Shift-P) за отваряне на командния палитър:**
**Разбиране на командния палет:**
- **Осигурява** бърз достъп до всички команди на VS Code
- **Търси** команди, докато пишете
**Разбиране на командния палитър:**
- **Предоставя** бърз достъп до всички команди на VS Code
- **Търси** команди докато пишете
- **Предлага** клавишни комбинации за по-бърза разработка
**Напишете "Live Server: Open with Live Server":**
**Какво прави Live Server:**
- **Стартира** локален сървър за разработка за вашия проект
- **Автоматично** обновява браузъра, когато запазвате файлове
- **Сервира** вашите файлове от локален URL (обикновено `localhost:5500`)
- **Стартира** локален сървър за разработка на проекта
- **Автоматично** презарежда браузъра при запис на файлове
- **Сървира** файловете ви от локален URL (обикновено `localhost:5500`)
**Отворете браузър и навигирайте до`https://localhost:5500`:**
**Отворете браузър и отидете на`https://localhost:5500`:**
Сега трябва да видите страницата, която създадохте! Нека добавим малко функционалност.
Сега трябва да видите страницата, която създадохте! Нека добавим функционалност.
## Добавяне на CSS
Сега нека направим нещата да изглеждат добре! Визуалната обратна връзка е била от решаващо значение за потребителските интерфейси още от ранните дни на компютрите. През 80-те години изследователите откриха, че незабавната визуална обратна връзка значително подобрява производителността на потребителите и намалява грешките. Точно това ще създадем.
Сега нека направим нещата да изглеждат добре! Визуалната обратна връзка е била ключова за потребителските интерфейси още от ранните дни на компютрите. През 80-те години изследователите откриват, че незабавната визуална обратна връзка значително подобрява представянето на потребителя и намалява грешките. Точно това ще създадем.
Нашата игра трябва да бъде кристално ясна за това, което се случва. Играчите трябва незабавно да знаят коя дума трябва да напишат, и ако направят грешка, трябва да я видят веднага. Нека създадем някои прости, но ефективни стилизации:
Нашата игра трябва да е кристално ясна за това какво се случва. Играчите веднага трябва да знаят коя дума трябва да напишат и ако направят грешка, да я виждат веднага. Нека създадем прост, но ефективен стил:
Създайте нов файл с име `style.css` и добавете следния синтаксис.
Създайте нов файл с име `style.css` и добавете следния код.
```css
/* inside style.css */
@ -232,35 +231,59 @@ code .
```
**Разбиране на тези CSS класове:**
- **Подчертава** текущата дума с жълт фон за ясна визуална насока
- **Сигнализира** за грешки при писане със светъл коралов цвят на фона
- **Осигурява** незабавна обратна връзка, без да прекъсва потока на писане на потребителя
- **Подчертава** текущата дума с жълт фон за ясно визуално насочване
- **Сигнализира** грешки в писането с мек коралов фон
- **Осигурява** незабавна обратна връзка без да нарушава потока на писане
- **Използва** контрастни цветове за достъпност и ясна визуална комуникация
✅ Що се отнася до CSS, можете да оформите страницата както ви харесва. Отделете малко време и направете страницата по-привлекателна:
✅ Когато става дума за CSS, можете да оформите страницата както пожелаете. Отделете малко време и направете страницата по-привлекателна:
- Изберете различен шрифт
- Оцветете заглавията
- Променете размерите на елементите
- Променете размера на елементите
## JavaScript
Тук става интересно! 🎉 Имаме структурата на HTML и стилизацията на CSS, но в момента нашата игра е като красива кола без двигател. JavaScript ще бъде този
Тук нещата стават интересни! 🎉 Имаме HTML структурата и CSS оформлението, но в момента нашата игра е като хубава кола без двигател. JavaScript ще бъде този двигател - той прави всичко да работи и да реагира на действията на играчите.
Тук ще видите как създанието ви оживява. Ще подхванем това стъпка по стъпка, за да не се чувствате претоварени:
| Стъпка | Цел | Какво ще научите |
|--------|-----|------------------|
| [Създаване на константите](../../../../4-typing-game/typing-game) | Настройване на цитати и референции към DOM | Управление на променливи и селекция в DOM |
| [Слушател на събития за стартиране на играта](../../../../4-typing-game/typing-game) | Обработка на инициализация на играта | Обработка на събития и обновяване на UI |
| [Слушател на събития за писане](../../../../4-typing-game/typing-game) | Обработка на потребителски вход в реално време | Проверкa на вход и динамична обратна връзка |
**Този структуриран подход ви помага:**
- **Организирате** кода в логически и управлявани секции
- **Изградите** функционалност постепенно за по-лесно отстраняване на грешки
- **Разберете** как различните части на приложението работят заедно
- **Създадете** повторно използваеми модели за бъдещи проекти
Но първо, създайте нов файл с име `script.js`.
### Добавяне на константите
Преди да се потопим в действието, нека съберем всичките си ресурси! Както контролният център на НАСА настройва всички си системи за наблюдение преди изстрелването, така и на нас ни е много по-лесно, когато имаме всичко подготвено и готово. Това ни спестява ровене по-късно и помага да избегнем правописни грешки.
Ето какво трябва първо да настроим:
| Тип данни | Цел | Пример |
| Масив от цитати | Съхранява всички възможни цитати за играта | `['Цитат 1', 'Цитат 2', ...]` |
| Масив от думи | Разделя текущия цитат на отделни думи | `['Когато', 'имаш', '...', ...]` |
| Индекс на думата | Следи коя дума пише играчът | `0, 1, 2, 3...` |
| Масив с думи | Разделя текущия цитат на отделни думи | `['Когато', 'имаш', ...]` |
| Индекс на думата | Следи коя дума играчът въвежда | `0, 1, 2, 3...` |
| Начално време | Изчислява изминалото време за оценяване | `Date.now()` |
**Ще ни трябват и препратки към елементите на потребителския интерфейс:**
**Също ще имаме нужда от препратки към нашите UI елементи:**
| Елемент | ID | Цел |
|---------|----|-----|
| Текстово поле | `typed-value` | Където играчите пишат |
| Показване на цитат | `quote` | Показва цитата за писане |
| Зона за съобщения | `message` | Показва актуализации на състоянието |
|---------|----|---------|
| Текстово поле за въвеждане | `typed-value` | Където играчите въвеждат |
| Показване на цитата | `quote` | Показва цитата за въвеждане |
| Област за съобщения | `message` | Показва актуализации на състоянието |
```javascript
// inside script.js
// all of our quotes
// вътре в script.js
// всички наши цитати
const quotes = [
'When you have eliminated the impossible, whatever remains, however improbable, must be the truth.',
'There is nothing more deceptive than an obvious fact.',
@ -270,261 +293,320 @@ const quotes = [
'Nothing clears up a case so much as stating it to another person.',
'Education never ends, Watson. It is a series of lessons, with the greatest for the last.',
];
// store the list of words and the index of the word the player is currently typing
// съхранява списъка с думи и индекса на думата, която играчът в момента въвежда
**Разглеждане на това, което прави този код за настройка:**
- **Съхранява** масив от цитати на Шерлок Холмс, използвайки`const`, тъй като цитатите няма да се променят
- **Инициализира** променливи за проследяване с`let`, тъй като тези стойности ще се актуализират по време на игра
- **Улавя** препратки към DOM елементи, използвайки`document.getElementById()` за ефективен достъп
- **Настройва** основата за цялата функционалност на игратас ясни, описателни имена на променливи
- **Организира** свързани данни и елементи логично за по-лесна поддръжка на кода
**Разбиване на това, което този код настройва:**
- **Съхранява** масив от цитати на Шерлок Холмсс`const`, тъй като цитатите няма да се променят
- **Инициализира** променливи за следене с`let`, тъй като тези стойности ще се обновяват по време на играта
- **Улавя** препратки към DOM елементис`document.getElementById()` за ефективен достъп
- **Настройва** основата за цялата игрова функционалност с ясни, описателни имена на променливи
- **Организира** свързаните данни и елементи логично за по-лесна поддръжка на кода
✅ Добавете още цитати към вашата игра
✅ Продължете и добавете още цитати към играта си
> 💡 **Полезен съвет**: Можем да извличаме елементите, когато пожелаем в кода, използвайки `document.getElementById()`. Тъй като често ще се обръщаме към тези елементи, ще избегнем грешки при изписването на низове, като използваме константи. Фреймуъркове като [Vue.js](https://vuejs.org/) или [React](https://reactjs.org/) могат да ви помогнат да управлявате по-добре централизирането на вашия код.
>
**Защо този подход работи толкова добре:**
- **Предотвратява** правописни грешки при многократно използване на елементи
- **Подобрява** четимостта на кода с описателни имена на константи
- **Позволява** по-добра поддръжка от IDE с автоматично допълване и проверка за грешки
- **Улеснява** рефакторинга, ако идентификаторите на елементите се променят по-късно
> 💡 **Полезен съвет**: Можем да извличаме елементите винаги, когато пожелаем в кода, използвайки `document.getElementById()`. Понеже ще се обръщаме към тези елементи често, за да избегнем правописни грешки при низовете използваме константи. Фреймуъркове като [Vue.js](https://vuejs.org/) или [React](https://reactjs.org/) могат да помогнат за по-добро центриране на кода ви.
>
**Ето защо този подход работи толкова добре:**
- **Предотвратява** правописни грешки при често рефериране към елементи
- **Подобряване** на четимостта на кода с описателни имена на константи
- **Позволява** по-добра поддръжка от IDE с автодовършване и проверка за грешки
- **Прави** рефакторинга по-лесен, ако по-късно се променят ID-тата на елементите
Отделете минута, за да гледате видео за използването на `const`, `let` и `var`
Отделете минута да гледате видео за използването на `const`, `let` и `var`
> 🎥 Кликнете върху изображението по-горе за видео за променливите.
> 🎥 Кликнете върху изображението по-горе за видео за променливи.
### Добавяне на логика за стартиране
### Добавяне на логика за старт
Тук всичко сесъбира на едно място! 🚀 Сега ще напишете първия си истински слушател на събития, и има нещо много удовлетворяващо в това да видите как вашият код реагира на натискане на бутон.
Тук всичко сесглобява! 🚀 Точно сега ще напишете първия си реален слушател на събития и има нещо много удовлетворяващо в това да видите кода си да реагира на натискане на бутон.
Помислете: някъде там играч ще натисне бутона "Старт", и вашият код трябва да е готов за него. Нямаме представа кога ще го натисне - може да е веднага, може да е след като си вземе кафе - но когато го направи, вашата игра оживява.
Помислете: някъде там, играч ще кликне на бутона „Старт“ и вашият код трябва да бъде готов за тях. Нямаме идея кога ще го направят - може веднага, може след като сипят кафе - но когато го направят, вашата игра оживява.
Когато потребителят натисне `start`, трябва да изберем цитат, да настроим потребителския интерфейс и да подготвим проследяването за текущата дума и времето. По-долу е JavaScript кодът, който трябва да добавите; ще го обсъдим веднага след блока със скрипта.
Когато потребителят кликне `start`, трябва да изберем цитат, да настроим потребителския интерфейс и да започнем следенето на текущата дума и времето. По-долу е JavaScript кодът, който трябва да добавите; ние го обсъждаме непосредствено след скрипта.
- **Позволява** точно изчисление на скоростта на писане и времето за завършване
- **Започва** проследяването на производителността за игровата сесия
**⏱️ Инициализация на таймера:**
- **Улавя** текущото време със `new Date().getTime()`
- **Позволява** точни изчисления на скоростта на писане и времето за завършване
- **Започва** следенето на времето за игровата сесия
### Добавяне на логика за писане
Тук се справяме със сърцето на нашата игра! Несе притеснявайте, ако това изглежда много в началото - ще преминем през всяка част, и накрая ще видите колко логично е всичко.
Тук стигаме до същността на играта! Несе притеснявайте, ако първоначално изглежда сложно - ще преминем през всяка част, и накрая ще видите колко логично е всичко.
Това, което изграждаме тук, е доста сложно: всеки път, когато някой напише буква, нашият код ще проверява какво е написано, ще дава обратна връзка и ще решава какво трябва да се случи след това. Това е подобно на начина, по който ранните текстови процесори като WordStar през 70-те години предоставяха обратна връзка в реално време на пишещите.
Това, което създаваме тук, е доста sofisticирано: всеки път когато някой напише буква, нашият код ще проверява какво е написал, ще дава обратна връзка и ще решава какво да се случи след това. Подобно е на ранните текстови процесори като WordStar от 70-те години, които осигуряваха обратна връзка в реално време.
Тази функция използва подход на водопад, проверявайки условията от най-специфичното към най-общото. Нека разгледаме всеки сценарий:
Тази функция използва метод "водопад", проверявайки условията от най-специфичното към най-общото. Нека разгледаме всеки сценарий:
```mermaid
flowchart TD
A[Player types character] --> B[Get current word and typed value]
B --> C{Quote complete?}
C -->|Yes| D[Show completion message with time]
C -->|No| E{Word complete with space?}
E -->|Yes| F[Clear input, move to next word, update highlight]
E -->|No| G{Typing correctly so far?}
G -->|Yes| H[Remove error styling]
G -->|No| I[Show error styling]
A[Играчът въвежда символ] --> B[Вземи текущата дума и въведената стойност]
B --> C{Цитатът завършен ли е?}
C -->|Да| D[Покажи съобщение за завършване с време]
C -->|Не| E{Думата завършва ли с интервал?}
E -->|Да| F[Изчисти въвеждането, премини към следващата дума, обнови маркирането]
E -->|Не| G{Правилно ли е въвеждането досега?}
G -->|Да| H[Премахни стилове за грешка]
G -->|Не| I[Покажи стилове за грешка]
```
**🏁 Завършен цитат (Сценарий 1):**
- **Проверява** дали въведената стойност съвпада с текущата дума И сме на последната дума
- **Изчислява** изминалото време, като изважда началното време от текущото време
- **Конвертира** милисекунди в секунди, като дели на 1,000
- **Показва** поздравително съобщение с времето за завършване
**✅ Завършена дума (Сценарий 2):**
- **Открива** завършване на дума, когато въведеното завършва с интервал
- **Проверява** дали подрязаният вход съвпада точно с текущата дума
- **Изчиства** полето за въвеждане за следващата дума
- **Преминава** към следващата дума, като увеличава `wordIndex`
- **Обновява** визуалното подчертаване, като премахва всички класове и подчертава новата дума
**📝 Напредък в писането (Сценарий 3):**
- **Проверява** дали текущата дума започва с това, което е написано досега
- **Премахва** всякакво стилизиране на грешки, за да покаже, че входът е правилен
- **Позволява** продължаване на писането без прекъсване
**❌ Състояние на грешка (Сценарий 4):**
- **Задейства** се, когато въведеният текст не съвпада с началото на очакваната дума
- **Прилага** CSS клас за грешка, за да предостави незабавна визуална обратна връзка
- **Помага** на играчите бързо да идентифицират и коригират грешките
**🏁 Цитатът е завършен (Сценарий 1):**
- **Проверява** дали въведеният текст съвпада с текущата дума И сме на последната дума
- **Изчислява** изминалото време като извади началното време от текущото
- **Преобразува** милисекунди в секунди, като дели на 1000
- **Показва** поздравително съобщение с времето за завършване
**✅ Думата е завършена (Сценарий 2):**
- **Открива** завършването на дума, когато въвеждането завършва с интервал
- **Потвърждава**, че изчистеният вход съвпада точно с текущата дума
- **Изчиства** полето за въвеждане за следващата дума
- **Премества** се към следващата дума чрез инкрементиране на `wordIndex`
- **Обновява** визуално подчертаване, като премахва всички класове и подчертава новата дума
**📝 Въвеждане в процес (Сценарий 3):**
- **Проверява**, че текущата дума започва с това, което вече е въведено
- **Премахва** всякакъв стил за грешка, за да покаже, че въвеждането е правилно
- **Позволява** продължаване на писането без прекъсване
**❌ Грешка в състоянието (Сценарий 4):**
- **Задейства** се, когато въведеният текст не съвпада с началото на очакваната дума
- **Прилага** CSS клас за грешка за незабавна визуална обратна връзка
- **Помага** на играчите бързо да идентифицират и коригират грешки
## Тествайте вашето приложение
Вижте какво сте постигнали! 🎉 Току-що изградихте истинска, работеща игра за писане от нулата, използвайки програмиране, базирано на събития. Отделете момент, за да оцените това - това не е малко постижение!
Вижте какво постигнахте! 🎉 Току-що изградихте истинска, работеща игра за писане от нулата, използвайки събитийно-ориентирано програмиране. Отделете момент да се насладите на това - не е никак маловажно!
Сега идва фазата на тестване! Ще работи ли както се очаква? Пропуснахме ли нещо? Ето какво: ако нещо не работи перфектно веднага, това е напълно нормално. Дори опитни разработчици редовно откриват грешки в своя код. Това е част от процеса на разработка!
Сега идва фазата на тестване! Ще работи ли според очакванията? Пропуснахме ли нещо? Истината е: ако нещо не работи перфектно първия път, това е напълно нормално. Дори опитните разработчици редовно намират бъгове в кода си. Това е част от процеса на развитие!
Кликнете върху `start` и започнете да пишете! Трябва да изглежда малко като анимацията, която видяхме преди.
Кликнете „start“ и започнете да пишете! Трябва да изглежда малко като анимацията, която видяхме преди.

**Какво да тествате във вашето приложение:**
- **Проверява** дали натискането на Start показва случаен цитат
- **Потвърждава** дали писането правилно подчертава текущата дума
- **Проверява** дали стилизирането на грешки се появява при неправилно писане
- **Уверява** се, че завършването на думите правилно премества подчертаването
- **Тества** дали завършването на цитата показва съобщение за завършване с време
**Какво да тествате в приложението си:**
- **Проверява** дали натискането на Старт показва случаен цитат
- **Уверява** се, че въвеждането подчертава правилно текущата дума
- **Проверява** дали се показва стил за грешка при некоректно писане
- **Гарантира** че завършването на думите премества подчертаването правилно
- **Тества** дали завършването на цитата показва съобщение за време
**Често срещани съвети за отстраняване на грешки:**
- **Проверете** конзолата на браузъра (F12) за грешки в JavaScript
- **Уверете се**, че всички имена на файлове съвпадат точно (чувствителни към малки и големи букви)
- **Уверете се**, че Live Server работи и сеобновява правилно
- **Тествайте** различни цитати, за да проверите дали случайният избор работи
**Често срещани съвети за отстраняване на грешки:**
- **Проверете** конзолата на браузъра (F12) за JavaScript грешки
- **Верифицирайте** дали всички имена на файлове съвпадат точно (различава се по големина на букви)
- **Уверете се, че** Live Server работи и обновява правилно страницата
- **Тествайте** различни цитати, за да проверите дали случаят избор работи
---
## Предизвикателство GitHub Copilot Agent 🎮
## Състезание с GitHub Copilot Agent 🎮
Използвайте режим Agent, за да завършите следното предизвикателство:
Използвайте режим Agent, за да изпълните следното предизвикателство:
**Описание:** Разширете играта за писане, като внедрите система за трудност, която се адаптира към представянето на играча. Това предизвикателство ще ви помогне да практикувате напреднало управление на събития, анализ на данни и динамични актуализации на потребителския интерфейс.
**Описание:** Разширете играта за писане, като реализирате система за трудност, която адаптира играта според представянето на играча. Това предизвикателство ще ви помогне да практикувате напреднало обработване на събития, анализ на данни и динамични UI ъпдейти.
**Задача:** Създайте система за регулиране на трудността за играта за писане, която:
1. Проследява скоростта на писане на играча (думи в минута) и процента на точност
2. Автоматично се адаптира към три нива на трудност: Лесно (прости цитати), Средно (текущи цитати), Трудно (сложни цитати с пунктуация)
3. Показва текущото ниво на трудност и статистиката на играча в потребителския интерфейс
4. Внедрява брояч на поредици, който увеличава трудността след 3 последователни добри представяния
5. Добавя визуална обратна връзка (цветове, анимации), за да посочи промените в трудността
**Подсказка:** Създайте система за адаптиране на трудността в играта, която:
1. Следи скоростта на писане на играча (думи в минута) и процента точност
2. Автоматично се адаптира към три нива на трудност: Лесно (прости цитати), Средно (текущите цитати), Трудно (сложни цитати с пунктуация)
3. Показва текущото ниво на трудност и статистики на играча в UI
4. Изпълнява брояч на серия от добри представяния, който увеличава трудността след 3 последователни успеха
5. Добавя визуална обратна връзка (цветове, анимации), която показва промените в трудността
Добавете необходимите HTML елементи, CSS стилове и JavaScript функции, за да внедрите тази функция. Включете подходящо обработване на грешки и се уверете, че играта остава достъпна с подходящи ARIA етикети.
Добавете необходимите HTML елементи, CSS стилове и JavaScript функции, за да реализирате тази функция. Включете подходяща обработка на грешки и гарантирайте, че играта остава достъпна с подходящи ARIA етикети.
Научете повече за [режим Agent](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
Научете повече за [Agent режима](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
## 🚀 Предизвикателство
Готови ли сте да издигнете играта си за писане на следващо ниво? Опитайте да внедрите тези напреднали функции, за да задълбочите разбирането си за управление на събития и манипулация на DOM:
Готови ли сте да издигнете играта си за писане на следващо ниво? Опитайте да внедрите тези разширени функции, за да задълбочите разбирането си за обработка на събития и манипулация на DOM:
**Добавете още функционалности:**
| Функция | Описание | Умения за практикуване |
|---------|----------|------------------------|
| **Контрол на въвеждането** | Деактивирайте event listener-a за `input` при завършване и го активирайте отново при натискане на бутона | Управление на събития и контрол на състояние |
| **Управление на UI състоянието** | Деактивирайте текстовото поле когато играчът завърши цитата | Манипулиране на DOM свойства |
| **Модален диалог** | Показва модален диалог с успех при завършване | Напреднали UI шаблони и достъпност |
| **Система за високи резултати** | Записва високи резултати с`localStorage` | API за съхранение в браузъра и съхранение на данни |
**Добавете повече функционалност:**
**Съвети за реализация:**
- **Разучете** `localStorage.setItem()` и `localStorage.getItem()` за устойчиво съхранение
- **Практикувайте** динамично добавяне и премахване на слушатели на събития
- **Изследвайте** HTML елементите dialog или CSS модални шаблони
- **Обмислете** достъпността при деактивиране и активиране на формови контролни елементи
| Функция | Описание | Умения, които ще практикувате |
| **Контрол на входа** | Деактивирайте слушателя на събития `input` при завършване и го активирайте отново, когато бутонът бъде натиснат | Управление на събития и контрол на състоянието |
| **Управление на състоянието на UI** | Деактивирайте текстовото поле, когато играчът завърши цитата | Манипулация на свойства на DOM |
| **Модален диалог** | Показване на модален диалогов прозорец със съобщение за успех | Напреднали UI модели и достъпност |
| **Система за високи резултати** | Съхранявайте високи резултати, използвайки `localStorage` | API за съхранение в браузъра и устойчивост на данни |
## Въпросник след лекцията
**Съвети за внедряване:**
- **Проучете** `localStorage.setItem()` и `localStorage.getItem()` за устойчиво съхранение
- **Практикувайте** добавяне и премахване на слушатели на събития динамично
- **Изследвайте** HTML елементи за диалог или CSS модели за модални прозорци
- **Обмислете** достъпността при деактивиране и активиране на контролите на формата
[Въпросник след лекцията](https://ff-quizzes.netlify.app/web/quiz/22)
---
## Тест след лекцията
## 🚀 Вашата времева линия за овладяване на играта за писане
### ⚡ **Какво можете да направите следващите 5 минути**
- [ ] Тествайте играта си с различни цитати, за да се уверите, че работи гладко
- [ ] Експериментирайте с CSS стилизирането - опитайте да промените цвета на подчертаване и грешка
- [ ] Отворете DevTools на браузъра (F12) и наблюдавайте Конзолата по време на игра
- [ ] Предизвикайте себе си да завършите цитат възможно най-бързо
### ⏰ **Какво можете да постигнете този час**
- [ ] Добавете още цитати в масива (може от любимите си книги или филми)
- [ ] Реализирайте системата за високи резултати с localStorage от секцията с предизвикателства
- [ ] Създайте калкулатор за думи в минута, който се показва след всяка игра
- [ ] Добавете звукови ефекти за правилно писане, грешки и завършване
### 📅 **Вашето приключение през седмицата**
- [ ] Изградете мултиплейър версия, където приятели могат да се състезават един до друг
- [ ] Създайте различни нива на трудност с различна сложност на цитатите
- [ ] Добавете прогрес бар, който показва колко от цитата е завършено
- [ ] Внедрете потребителски акаунти с проследяване на лична статистика
- [ ] Дизайн на персонализирани теми, които потребителите да избират
### 🗓️ **Вашата трансформация през месеца**
- [ ] Създайте курс за писане с уроци, които постепенно учат на правилно разположение на пръстите
- [ ] Изградете аналитика, която показва кои букви или думи причиняват най-много грешки
- [ ] Добавете поддръжка за различни езици и клавиатурни разположения
- [ ] Интегрирайте сес образователни API-та за извличане на цитати от литературни бази данни
- [ ] Публикувайте разширената си игра за писане, за да могат други да я използват и да се забавляват
### 🎯 **Последна проверка на самоотразяване**
**Преди да продължите, отделете момент да отбележите:**
- Кой беше най-удовлетворяващият момент при изграждането на тази игра?
- Как се чувствате сега относно събитийно-ориентираното програмиране в сравнение с началото?
- Коя функция бихте искали да добавите, за да направите играта уникална?
- Как бихте приложили концепциите за обработка на събития в други проекти?
[Тест след лекцията](https://ff-quizzes.netlify.app/web/quiz/22)
```mermaid
journey
title Вашето пътешествие към увереност при програмиране на събития
section Днес
Разбиране на събитията: 3: You
Създаване на потребителски интерфейс: 4: You
Писане на слушатели на събития: 5: You
section Тази седмица
Добавяне на функции: 4: You
Отстраняване на грешки: 5: You
Подобряване на потребителския опит: 4: You
section Следващия месец
Създаване на сложни приложения: 5: You
Обучение на други: 5: You
Създаване на рамки: 5: You
```
> 🌟 **Запомнете**: Току-що овладяхте една от основните концепции, които задвижват всяка интерактивна уеб страница и приложение. Събитийно-ориентираното програмиране е това, което прави уеба жив и отзивчив. Всеки път, когато видите падащо меню, форма, която валидира докато пишете, или игра, която реагира на кликвания, вече разбирате магията зад това. Не просто учите да програмирате - учите се да създавате преживявания, които се усещат интуитивни и ангажиращи! 🎉
---
## Преглед и самостоятелно обучение
Прочетете за [всички налични събития](https://developer.mozilla.org/docs/Web/Events), които разработчикът може да използва чрез уеб браузъра, и обмислете сценариите, в които бихте използвали всяко от тях.
Прочетете за [всички събития, достъпни](https://developer.mozilla.org/docs/Web/Events) на разработчика чрез уеб браузъра и обмислете в кои ситуации бихте използвали всяко от тях.
## Задание
## Задача
[Създайте нова игра с клавиатура](assignment.md)
---
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Отказ от отговорност**:
Този документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.
Този документ е преведен с помощта на AI преводаческа услуга [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматичните преводи могат да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човешки преводач. Не носим отговорност за каквито и да е недоразумения или неправилни тълкувания, произтичащи от използването на този превод.
Браузърните разширения са мини-приложения, които подобряват вашето преживяване при сърфиране в интернет. Подобно на оригиналната визия на Тим Бърнърс-Лий за интерактивен уеб, разширенията разширяват възможностите на браузъра отвъд простото разглеждане на документи. От мениджъри на пароли, които защитават вашите акаунти, до инструменти за избор на цветове, които помагат на дизайнерите да намерят перфектните нюанси, разширенията решават ежедневни предизвикателства при сърфиране.
Разширенията за браузърса мини-приложения, които подобряват вашето сърфиране в интернет. Подобно на оригиналната визия на Тим Бърнърс-Лий за интерактивен уеб, разширенията разширяват възможностите на браузъра отвъд просто показване на документи. От мениджъри на пароли, които пазят вашите акаунти в безопасност, до инструменти за избор на цветове, които помагат на дизайнерите да вземат перфектния нюанс — разширенията решават ежедневни предизвикателства при сърфиране.
Преди да създадем вашето първо разширение, нека разберем как работят браузърите. Точно както Александър Греъм Бел е трябвало да разбере предаването на звук преди да изобрети телефона, познаването на основите на браузърите ще ви помогне да създадете разширения, които се интегрират безпроблемно със съществуващите системи на браузъра.
Преди да създадем първото ви разширение, нека разберем как работят браузърите. Точно както Александър Греъм Бел трябваше да разбере предаването на звук, преди да изобрети телефона, познаването на основите на браузърите ще ви помогне да създавате разширения, които се интегрират безпроблемно със съществуващите браузърни системи.
До края на този урок ще разберете архитектурата на браузърите и ще започнете да изграждате своето първо разширение.
В края на този урок ще разберете архитектурата на браузъра и ще започнете да изграждате първото си разширение.
```mermaid
mindmap
root((Архитектура на браузъра))
Core Components
Рендиращ двигател
JavaScript двигател
Мрежов стек
API за съхранение
User Interface
Адресна лента
Управление на табове
Отметки
Икони на разширения
Extension System
Манифестни файлове
Скриптове за съдържание
Фонови страници
Изскачащи прозорци
Security Model
Политика на един и същ произход
API за разрешения
Сигурност на съдържанието
Изолирани светове
Development Tools
Интеграция на DevTools
Конзола за отстраняване на грешки
Монитор на производителността
Инспектор на разширения
```
## Разбиране на уеб браузърите
Уеб браузърът е по същество сложен интерпретатор на документи. Когато въведете "google.com" в адресната лента, браузърът извършва сложна серия от операции - заявява съдържание от сървъри по целия свят, след това анализира и визуализира този код в интерактивните уеб страници, които виждате.
Уеб браузърът е по същество сложен интерпретатор на документи. Когато напишете "google.com" в адресната лента, браузърът извършва сложна поредица от операции - заявявайки съдържание от сървъри по целия свят, след което анализира и визуализира този код в интерактивните уеб страници, които виждате.
Този процес наподобява начина, по който първият уеб браузър, WorldWideWeb, е бил проектиран от Тим Бърнърс-Лий през 1990 г., за да направи хипервръзките достъпни за всички.
Този процес отразява начина, по който първият уеб браузър, WorldWideWeb, беше проектиран от Тим Бърнърс-Лий през 1990 г., за да направи хипервръзки достъпни за всеки.
✅ **Малко история**: Първият браузър сее наричал 'WorldWideWeb' и е бил създаден от сър Тимъти Бърнърс-Лий през 1990 г.
✅ **Малко история**: Първият браузър секазваше 'WorldWideWeb' и беше създаден от сър Тимъти Бърнърс-Лий през 1990 г.
Extension->>Extension: Променя съдържанието, ако е необходимо
Browser->>User: Зарежда цялата уеб страница
Extension->>User: Показва актуализации на UI на разширението
```
**Ето какво осъществява този процес:**
- **Превежда** URL адреса, разбираем за хората, в IP адрес на сървър чрез DNS заявка
- **Установява** сигурна връзка със уеб сървъра чрез HTTP или HTTPS протоколи
- **Заявява** конкретното съдържание на уеб страницата от сървъра
- **Получава** HTML маркиране, CSS стилизиране и JavaScript код от сървъра
- **Визуализира** цялото съдържание като интерактивна уеб страница, която виждате
**Ето какво постига този процес:**
- **Превежда** четимия за хората URL в IP адрес на сървъра чрез DNS търсене
- **Установява** сигурна връзка суеб сървъра, използвайки HTTP или HTTPS протоколи
- **Заявява** специфичното съдържание на уеб страницата от сървъра
- **Получава** HTML код, CSS стилове и JavaScript код от сървъра
- **Визуализира** цялото съдържание в интерактивната уеб страница, която виждате
### Основни функции на браузърите
### Основни функции на браузъра
Съвременните браузъри предоставят множество функции, които разработчиците на разширения могат да използват:
Съвременните браузъри предлагат множество функции, които разработчиците на разширения могат да използват:
| Функция | Цел | Възможности за разширения |
|---------|---------|------------------------|
| **Енджин за визуализация** | Показва HTML, CSS и JavaScript | Модификация на съдържание, инжектиране на стилове |
| **JavaScript енджин** | Изпълнява JavaScript код | Персонализирани скриптове, взаимодействие с API |
| **Локално съхранение** | Запазва данни локално | Потребителски предпочитания, кеширани данни |
| **Мрежов стек** | Обработва уеб заявки | Мониторинг на заявки, анализ на данни |
| **Модел за сигурност** | Защитава потребителите от злонамерено съдържание | Филтриране на съдържание, подобренияв сигурността |
| **Рендеринг енджин** | Показва HTML, CSS и JavaScript | Модификация на съдържание, вмъкване на стилове |
| **JavaScript енджин** | Изпълнява JavaScript код | Потребителски скриптове, взаимодействие с API |
| **Локално съхранение** | Запазва данни локално | Потребителски настройки, кеширани данни |
| **Мрежова стека** | Обработва уеб заявки | Мониторинг на заявки, анализ на данни |
| **Модел за сигурност** | Защитава потребителите от злонамерено съдържание | Филтриране на съдържание, подобряване на сигурността |
**Разбирането на тези функции ви помага:**
- **Да идентифицирате** къде вашето разширение може да добави най-голяма стойност
- **Да изберете** правилните браузърни API за функционалността на вашето разширение
- **Да проектирате** разширения, които работят ефективно със системите на браузъра
- **Да гарантирате**, че вашето разширение следва най-добрите практики за сигурност на браузъра
- **Идентифицирате** къде вашето разширение може да добави най-голяма стойност
- **Избирате** правилните браузърни API-та за функционалността на вашето разширение
- **Проектирате** разширения, които работят ефективно с браузърните системи
- **Осигурявате** спазването на най-добрите практики за сигурност на браузъра
### Съображения за разработка на разширения за различни браузъри
### Съображения при разработка за различни браузъри
Различните браузъри прилагат стандартите с леки вариации, подобно на начина, по който различните програмни езици могат да обработват един и същ алгоритъм по различен начин. Chrome, Firefox и Safari имат уникални характеристики, които разработчиците трябва да вземат предвид при разработката на разширения.
Различните браузъри прилагат стандартите с леки вариации, подобно на това как различни програмни езици може да обработват един и същи алгоритъм по различен начин. Chrome, Firefox и Safari имат уникални характеристики, които разработчиците трябва да имат предвид при създаване на разширения.
> 💡 **Съвет**: Използвайте [caniuse.com](https://www.caniuse.com), за да проверите кои уеб технологии се поддържат в различните браузъри. Това е безценно при планирането на функциите на вашето разширение!
> 💡 **Съвет от професионалист**: Използвайте [caniuse.com](https://www.caniuse.com), за да проверите кои уеб технологии се поддържат в отделните браузъри. Това е безценно при планиране на функциите на разширението ви!
**Основни съображения за разработка на разширения:**
- **Тествайте** вашето разширение в браузърите Chrome, Firefox и Edge
- **Адаптирайте** към различните API за разширения и формати на манифеста
- **Справяйте се** с различни характеристики на производителността и ограниченията
- **Осигурете** резервни варианти за специфични функции на браузъра, които може да не са налични
**Ключови съображения за разработка на разширения:**
- **Тествайте** разширението си в Chrome, Firefox и Edge
- **Адаптирайте** се към различни браузърни API-та и формати на манифест
- **Обработвайте** различни характеристики на производителността и ограничения
- **Осигурявайте** резервни решения за браузърно-специфични функции, които може да не са достъпни
✅ **Аналитична информация**: Можете да определите кои браузъри предпочитат вашите потребители, като инсталирате аналитични пакети в проектите си за уеб разработка. Тези данни ще ви помогнат да приоритизирате кои браузъри да поддържате първо.
✅ **Аналитично наблюдение**: Можете да определите кои браузъри предпочитат вашите потребители, като инсталирате аналитични пакети в своите уеб проекти. Тези данни помагат да приоритизирате подкрепата за определени браузъри.
## Разбиране на браузърните разширения
## Разбиране на разширенията за браузър
Браузърните разширения решават често срещани предизвикателства при сърфиране, като добавят функционалност директно към интерфейса на браузъра. Вместо да изискват отделни приложения или сложни работни процеси, разширенията предоставят незабавен достъп до инструменти и функции.
Разширенията за браузър решават често срещани проблеми при сърфиране, като добавят функционалност директно към интерфейса на браузъра. Вместо да изискват отделни приложения или сложни работни потоци, разширенията предоставят незабавен достъп до инструменти и функции.
Тази концепция наподобява как ранните компютърни пионери като Дъглас Енгелбарт са си представяли разширяване на човешките способности чрез технологии - разширенията разширяват основната функционалност на вашия браузър.
Това е концепция, която отразява визията на ранните пионери в компютърната област като Дъглас Енгелбарт да увеличат човешките възможности чрез технология — разширенията увеличават базовата функционалност на вашия браузър.
```mermaid
quadrantChart
title Категории Разширения за Браузър
x-axis Просто --> Сложно
y-axis Лично Използване --> Професионални Инструменти
quadrant-1 Инструменти за Разработчици
quadrant-2 Предприятия Решения
quadrant-3 Лични Помощни Средства
quadrant-4 Приложения за Продуктивност
Ad Blockers: [0.3, 0.2]
Password Managers: [0.7, 0.3]
Color Pickers: [0.4, 0.8]
Code Formatters: [0.8, 0.9]
Note Taking: [0.6, 0.5]
Video Downloaders: [0.5, 0.2]
Time Trackers: [0.7, 0.6]
Screenshot Tools: [0.4, 0.4]
```
**Популярни категории разширения и техните предимства:**
- **Инструменти за продуктивност**: Мениджъри на задачи, приложения за водене на бележки и тракери на време, които ви помагат да останете организирани
- **Подобрения в сигурността**: Мениджъри на пароли, блокиращи реклами и инструменти за поверителност, които защитават вашите данни
- **Инструменти за разработчици**: Форматори на код, инструменти за избор на цветове и помощни средства за дебъгване, които улесняват разработката
- **Подобрения на съдържанието**: Режими за четене, инструменти за изтегляне на видеа и инструменти за скрийншоти, които подобряват вашето уеб преживяване
✅ **Въпрос за размисъл**: Кои са вашите любими браузърни разширения? Какви конкретни задачи изпълняват и как подобряват вашето преживяване при сърфиране?
- **Инструменти за продуктивност**: Мениджъри на задачи, приложения за водене на бележки и тракери за време, които помагат за по-добра организация
- **Подобрения в сигурността**: Мениджъри на пароли, блокиращи реклами, инструменти за защита на поверителността, които пазят вашите данни
- **Инструменти за разработчици**: Форматори на код, инструменти за избор на цветове и дебъгинг, които улесняват разработката
- **Подобрения на съдържанието**: Режими за четене, изтеглящи видео файлове и инструменти за екранни снимки, които подобряват изживяването при сърфиране
✅ **Въпрос за размисъл**: Кои са любимите ви разширения за браузър? Какви конкретни задачи изпълняват и как подобряват сърфирането ви?
### 🔄 **Педагогически проверка**
**Разбиране на архитектурата на браузърите**: Преди да преминете към разработка на разширения, уверете се, че можете:
- ✅ Да обясните как браузърите обработват уеб заявки и визуализират съдържание
- ✅ Да идентифицирате основните компоненти на архитектурата на браузъра
- ✅ Да разберете как разширенията се интегрират с функционалността на браузъра
- ✅ Да познавате модела за сигурност, който защитава потребителите
**Бърз самотест**: Можете ли да проследите пътя от въвеждането на URL до показването на уеб страница?
1. **DNS заявка** превръща URL в IP адрес
2. **HTTP заявка** извлича съдържание от сървъра
3. **Анализ** обработва HTML, CSS и JavaScript
4. **Рендериране** показва крайния уебсайт
5. **Разширенията** могат да модифицират съдържание на няколко етапа
## Инсталиране и управление на разширения
Разбирането на процеса на инсталиране на разширения помага да предвидите потребителското преживяване, когато хората инсталират вашето разширение. Процесът на инсталиране е стандартизиран в съвременните браузъри, с малки вариации в дизайна на интерфейса.
Разбирането на процеса по инсталация на разширения помага да предвидите потребителското изживяване при инсталиране на вашето разширение. Този процес е стандартизиран във всички съвременни браузъри, с малки различия в дизайна на интерфейса.


> **Важно**: Уверете се, че сте активирали режим за разработчици и сте разрешили разширения от други магазини, когато тествате собствените си разширения.
> **Важно**: Уверете се, че сте активирали режим за разработчици и разрешили разширения от други магазини, когато тествате собствените си разширения.
### Процес на инсталиране на разширения за разработка
### Процес на инсталиране на разширения по време на разработка
Когато разработвате и тествате собствените си разширения, следвайте този работен процес:
Когато разработвате и тествате своите разширения, следвайте тази последователност:
```mermaid
flowchart TD
A[Напиши код] --> B[Изграждане на разширение]
B --> C{Първа инсталация?}
C -->|Да| D[Зареди разархивирано]
C -->|Не| E[Презареди разширението]
D --> F[Тествай функционалността]
E --> F
F --> G{Работи правилно?}
G -->|Не| H[Отстрани проблемите]
G -->|Да| I[Готово за потребителите]
H --> A
I --> J[Публикувай в магазина]
style A fill:#e1f5fe
style F fill:#e8f5e8
style I fill:#f3e5f5
style J fill:#fff3e0
```
```bash
# Step 1: Build your extension
# Стъпка 1: Създайте вашето разширение
npm run build
```
**Какво постига тази команда:**
- **Компилира** вашия изходен код във файлове, готови за браузъра
**Ето какво постига тази команда:**
- **Компилира** изходния ви код в готови за браузър файлове
- **Пакетира** JavaScript модулите в оптимизирани пакети
- **Генерира** финалните файлове на разширението в папката `/dist`
- **Подготвя** вашето разширение за инсталиране и тестване
- **Генерира** окончателните файлове на разширението в папката `/dist`
- **Подготвя** разширението ви за инсталация и тестване
**Стъпка 2: Навигирайте до разширенията на браузъра**
1. **Отворете** страницата за управление на разширенията на вашия браузър
2. **Кликнете** върху бутона "Настройки и още" (иконата `...`) в горния десен ъгъл
**Стъпка 2: Навигирайте до разширения на браузъра**
1. **Отворете** страницата за управление на разширенията в браузъра
2. **Щракнете** бутона "Настройки и още" (иконата `...`) в горния десен ъгъл
3. **Изберете** "Разширения" от падащото меню
**Стъпка 3: Заредете вашето разширение**
- **За нови инсталации**: Изберете `load unpacked` и изберете вашата папка `/dist`
- **За актуализации**: Кликнете върху `reload` до вече инсталираното разширение
- **За тестване**: Активирайте "Режим за разработчици", за да получите достъп до допълнителни функции за дебъгване
**Стъпка 3: Зареждане на разширението**
- **За нова инсталация**: Изберете `load unpacked` и посочете папката`/dist`
- **Заъпдейти**: Щракнете`reload` до вече инсталирано разширение
- **За тестване**: Активирайте "Режим за разработчици" за достъп до по-дълбоки функции за дебъгинг
### Инсталиране на разширение за продукция
### Инсталиране на разширения в продукция
> ✅ **Забележка**: Тези инструкции за разработка саспециално за разширения, които създавате сами. За да инсталирате публикувани разширения, посетете официалните магазини за браузърни разширения като [Microsoft Edge Add-ons store](https://microsoftedge.microsoft.com/addons/Microsoft-Edge-Extensions-Home).
> ✅ **Забележка**: Тези инструкции за разработка сапредназначени за разширения, които сами създавате. За инсталиране на публикувани разширения, посетете официалните магазини за разширения, като [Microsoft Edge Add-ons store](https://microsoftedge.microsoft.com/addons/Microsoft-Edge-Extensions-Home).
**Разбиране на разликата:**
- **Инсталациите за разработка** ви позволяват да тествате непубликувани разширения по време на разработката
- **Инсталациите от магазините** предоставят проверени, публикувани разширения с автоматични актуализации
- **Ръчно инсталиране** позволява инсталиране на разширения извън официалните магазини (изисква режим за разработчици)
- **Разработващи инсталации** позволяват тестване на непубликувани разширения по време на разработка
- **Инсталации от магазина** предлагат проверени, публикувани разширения с автоматични ъпдейти
- **Сайдлоудинг** позволява инсталиране на разширения от външни източници (изисква режим за разработчици)
## Създаване на разширение за въглероден отпечатък
## Създаване на разширението за въглеродния отпечатък
Ще създадем браузърно разширение, което показва въглеродния отпечатък от използването на енергия във вашия регион. Този проект демонстрира основни концепции за разработка на разширения, като същевременно създава практичен инструмент за повишаване на екологичната осведоменост.
Ще създадем разширение за браузър, което показва въглеродния отпечатък от енергопотреблението във вашия регион. Този проект демонстрира основни концепции за разработка на разширения, докато създава практичен инструмент за екологично съзнание.
Този подход следва принципа "учене чрез правене", който сее доказал като ефективен още от образователните теории на Джон Дюи - съчетавайки технически умения със значими реални приложения.
Този подход следва принципа "учене чрез правене", доказано ефективен от образователните теории на Джон Дюи - комбиниране на технически умения със значими приложения в реалния свят.
### Изисквания за проекта
### Изисквания към проекта
Преди да започнем разработката, нека съберем необходимите ресурси и зависимости:
Преди да започнете разработката, нека съберем необходимите ресурси и зависимости:
**Необходим достъп до API:**
- **[CO2 Signal API ключ](https://www.co2signal.com/)**: Въведете вашия имейл адрес, за да получите безплатен API ключ
- **[Код на регион](http://api.electricitymap.org/v3/zones)**: Намерете кода на вашия регион, използвайки [Electricity Map](https://www.electricitymap.org/map) (например, Бостън използва 'US-NEISO')
**Изискван достъп до API:**
- **[API ключ за CO2 Signal](https://www.co2signal.com/)**: Въведете своя имейл адрес, за да получите безплатния си ключ
- **[Код на регион](http://api.electricitymap.org/v3/zones)**: Намерете кода на своя регион в [Electricity Map](https://www.electricitymap.org/map) (например, Бостън използва 'US-NEISO')
**Инструменти за разработка:**
- **[Node.js и NPM](https://www.npmjs.com)**: Инструмент за управление на пакети за инсталиране на зависимости на проекта
- **[Начален код](../../../../5-browser-extension/start)**: Изтеглете папката`start`, за да започнете разработката
- **[Node.js и NPM](https://www.npmjs.com)**: Инструменти за управление на пакети за инсталиране на зависимости
- **[Начален код](../../../../5-browser-extension/start)**: Изтеглете папка `start`, за да започнете разработката
✅ **Научете повече**: Подобрете уменията си за управление на пакети с този [подробен модул за обучение](https://docs.microsoft.com/learn/modules/create-nodejs-project-dependencies/?WT.mc_id=academic-77807-sagibbon)
✅ **Научете повече**: Подобрете уменията си за управление на пакети с този [изчерпателен Learn модул](https://docs.microsoft.com/learn/modules/create-nodejs-project-dependencies/?WT.mc_id=academic-77807-sagibbon)
### Разбиране на структурата на проекта
Разбирането на структурата на проекта помага за организиране на работата по разработката ефективно. Точно както библиотеката в Александрия е била организирана за лесно извличане на знания, добре структурираният код прави разработката по-ефективна:
Разбирането на структурата на проекта помага за ефективна организация на разработката. Подобно на това как Александрийската библиотека беше организирана за лесен достъп до знание, добре структурирана кодова база прави разработката по-ефективна:
├── package.json # Project dependencies and scripts
└── webpack.config.js # Build configuration
```
**Разбивка на това, което постига всеки файл:**
- **`manifest.json`**: **Определя** метаданни за разширението, разрешения и входни точки
- **`index.html`**: **Създава** потребителския интерфейс, който се появява, когато потребителите кликнат върху вашето разширение
- **`background.js`**: **Обработва** фонови задачи и слушатели на събития в браузъра
- **`main.js`**: **Съдържа** финалния пакетен JavaScript след процеса на компилация
- **`src/index.js`**: **Съхранява** основния код за разработка, който се компилира в `main.js`
**Разглобяване на функционалността на всеки файл:**
- **`manifest.json`**: **Дефинира** метаданните на разширението, разрешенията и входните точки
- **`index.html`**: **Създава** потребителския интерфейс, който се появява при клик върху разширението
- **`background.js`**: **Обработва** фонови задачи и слушатели на събития на браузъра
- **`main.js`**: **Съдържа** окончателния пакет JavaScript след процеса на компилация
- **`src/index.js`**: **Кодира** основния код за разработка, който се компилира в `main.js`
> 💡 **Съвет за организация**: Съхранявайте вашия API ключ и код на региона в защитена бележка за лесен достъп по време на разработката. Ще ви трябват тези стойности, за да тествате функционалността на вашето разширение.
> 💡 **Съвет за организация**: Запишете своя API ключ и регионалния код в сигурна бележка за лесен достъп по време на разработка. Тези данни ще са ви необходими за тестване на функционалността на разширението.
✅ **Забележка за сигурност**: Никога не качвайте API ключове или чувствителни данни в хранилището на вашия код. Ще ви покажем как да се справите с тях безопасно в следващите стъпки.
✅ **Съвет за сигурност**: Никога не вкарвайте API ключове или чувствителни данни в хранилището на кода. Ще ви покажем как да ги управлявате сигурно в следващите стъпки.
## Създаване на интерфейса на разширението
Сега ще изградим компонентите на потребителския интерфейс. Разширението използва подход с два екрана: екран за конфигурация за първоначална настройка и екран за резултати за показване на данни.
Сега ще изградим компонентите на потребителския интерфейс. Разширението използва двусекционен подход: екран за конфигурация при първоначална настройка и екран с резултати за показване на данни.
Това следва принципа на прогресивно разкриване, използван в дизайна на интерфейси още от ранните дни на компютърните технологии - разкриване на информация и опции в логична последователност, за да се избегне претоварване на потребителите.
Това следва принципа за прогресивно разкриване, използван в дизайна на интерфейси още от ранните компютърни дни - разкриване на информация и опции в логична последователност, за да не се претоварват потребителите.
### Преглед на изгледите на разширението
**Изглед за настройка** - Конфигурация за първоначална употреба:

**Екран за настройка** - Конфигурация при първото използване:

**Изглед за резултати** - Показване на данни за въглеродния отпечатък:

**Екран с резултати** - Показване на данните за въглеродния отпечатък:

### Създаване на формуляр за конфигурация
### Изграждане на формата за конфигурация
Формулярът за настройка събира данни за конфигурация от потребителя при първоначална употреба. След като бъде конфигуриран, тази информация се запазва в паметта на браузъра за бъдещи сесии.
Формата за настройка събира данни от потребителя при първото използване. След конфигурация, тази информация се запазва в браузърното хранилище за бъдещи сесии.
Във файла `/dist/index.html` добавете тази структура на формуляра:
Във файла `/dist/index.html` добавете тази структура на формата:
```html
<formclass="form-data"autocomplete="on">
@ -232,41 +336,220 @@ project-root/
</form>
```
**Ето какво постига този формуляр:**
- **Създава** семантична структура на формуляра с правилни етикети и асоциации на полетата
- **Активира** функционалността за автоматично попълване на браузъра за подобрено потребителско преживяване
- **Изисква** попълване на двете полета преди изпращане, използвайки атрибута `required`
- **Организира** полетата с описателни имена на класове за лесно стилизиране и насочване чрез JavaScript
- **Осигурява** ясни инструкции за потребителите,
**Описание:** Подобрете разширението за браузър, като добавите функции за валидиране на формуляри и обратна връзка към потребителя, за да подобрите потребителското изживяване при въвеждане на API ключове и кодове на региони.
**Ето какво осигурява тази форма:**
- **Създава** семантична структура с подходящи етикети и асоциации на полета
- **Активира** функциите за автоматично довършване на браузъра за подобрено потребителско изживяване
- **Изисква** попълване на всички полета преди подаване чрез атрибута `required`
- **Организира** полетата с описателни имена на класове за лесна стилизация и JavaScript насочване
- **Предоставя** ясни инструкции за потребителите, които настройват разширението за първи път
### Изграждане на екран за показване на резултати
След това създайте областта за резултати, която ще показва данните за въглеродния отпечатък. Добавете този HTML под формата:
- **`loading`**: **Показва** съобщение за зареждане, докато се извличат данни от API
- **`errors`**: **Показва** съобщения за грешки при неуспешни API заявки или невалидни данни
- **`data`**: **Съдържа** сурови данни за целите на дебъгинг по време на разработка
- **`result-container`**: **Презентира** форматирана информация за въглеродния отпечатък на потребителите
- **`clear-btn`**: **Позволява** на потребителите да променят своя регион и да пре-конфигурират разширението
**Задача:** Създайте JavaScript функции за валидиране, които проверяват дали полето за API ключ съдържа поне 20 символа и дали кодът на региона следва правилния формат (например 'US-NEISO'). Добавете визуална обратна връзка, като променяте цвета на рамката на полето за въвеждане на зелено за валидни данни и червено за невалидни. Освен това добавете функция за превключване, която позволява показване/скриване на API ключа за сигурност.
### Настройване на процеса за компилация
Научете повече за [режим агент](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
Сега нека инсталираме зависимостите на проекта и тестваме процеса на компилация:
## 🚀 Предизвикателство
```bash
npm install
```
Разгледайте магазин за разширения за браузър и инсталирайте едно на вашия браузър. Можете да изследвате неговите файлове по интересни начини. Какво откривате?
**Какво постигаме с този процес на инсталация:**
- **Изтегля** Webpack и други зависимости за разработка, посочени в `package.json`
- **Конфигурира** инструментариума за компилиране на съвременен JavaScript
- **Подготвя** средата за разработка за изграждане и тестване на разширение
- **Позволява** пакетиране на код, оптимизация и съвместимост с различни браузъри
## Тест след лекцията
> 💡 **Информация за процеса на компилация**: Webpack пакетира вашия изходен код от `/src/index.js` в `/dist/main.js`. Този процес оптимизира кода за продукция и осигурява съвместимост с браузърите.
[Тест след лекцията](https://ff-quizzes.netlify.app/web/quiz/24)
### Тестване на напредъка
## Преглед и самостоятелно обучение
В този момент можете да тествате разширението си:
1. **Изпълнете** командата за билд, за да компилирате кода си
2. **Заредете** разширението в браузъра си, като използвате режим за разработчици
3. **Проверете**, че формата се показва правилно и изглежда професионално
4. **Уверете се**, че всички елементи на формата са правилно подравнени и функционални
В този урок научихте малко за историята на уеб браузъра; използвайте тази възможност, за да научите повече за това как създателите на Световната мрежа са си представяли нейното използване, като прочетете повече за нейната история. Някои полезни сайтове включват:
**Какво сте постигнали:**
- **Построихте** основната HTML структура за вашето разширение
- **Създадохте** интерфейси за конфигурация и резултати с правилна семантична маркировка
- **Настроихте** съвременен работен процес с използване на индустриални инструменти
- **Подготвихте** основата за добавяне на интерактивна JavaScript функционалност
[История на уеб браузърите](https://www.mozilla.org/firefox/browsers/browser-history/)
### 🔄 **Педагогическа проверка**
**Прогрес в разработката на разширение**: Проверете разбирането си преди да продължите:
- ✅ Можете ли да обясните предназначението на всеки файл в структурата на проекта?
- ✅ Разбирате ли как процесът на билд превръща изходния ви код?
- ✅ Защо разделяме конфигурацията и резултатите в различни UI секции?
- ✅ Как структурата на формата поддържа както удобство за ползване, така и достъпност?
[История на уеб](https://webfoundation.org/about/vision/history-of-the-web/)
**Разбиране на работния процес на разработка**: Вече би трябвало да можете да:
1. **Модифицирате** HTML и CSS за интерфейса на разширението си
2. **Изпълните** командата за билд, за да компилирате промените
3. **Презаредите** разширението в браузъра, за да тествате актуализациите
4. **Отстранявате грешки** с помощта на инструментите за разработчици на браузъра
[Интервю с Тим Бърнърс-Лий](https://www.theguardian.com/technology/2019/mar/12/tim-berners-lee-on-30-years-of-the-web-if-we-dream-a-little-we-can-get-the-web-we-want)
Завършихте първия етап от разработката на браузърно разширение. Както братята Райт първо трябваше да разберат аеродинамиката преди да постигнат полет, така и разбирането на тези основни концепции ви подготвя за изграждане на по-сложни интерактивни функции в следващия урок.
## Задача
## GitHub Copilot Agent Challenge 🚀
[Променете стила на вашето разширение](assignment.md)
Използвайте режим Agent, за да изпълните следното предизвикателство:
**Описание:** Подобрете браузърното разширение, като добавите валидиране на формата и функции за обратна връзка към потребителя, за да подобрите потребителския опит при въвеждане на API ключове и регионални кодове.
**Подсказка:** Създайте JavaScript функции за валидиране, които проверяват дали полето за API ключ съдържа поне 20 знака и дали регионалният код е във верния формат (като 'US-NEISO'). Добавете визуална обратна връзка чрез промяна на цвета на рамката на полето в зелено за валидни и в червено за невалидни стойности. Също добавете функция за превключване на видимостта на API ключа за целите на сигурността.
Научете повече за [режим agent](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
## 🚀 Предизвикателство
Разгледайте магазин за браузърни разширения и инсталирайте едно в браузъра си. Можете да разгледате файловете му по интересни начини. Какво откривате?
## Квиз след лекцията
[Квиз след лекцията](https://ff-quizzes.netlify.app/web/quiz/24)
## Преглед и самостоятелно изучаване
В този урок научихте малко за историята на уеб браузъра; използвайте тази възможност да научите повече за начина, по който изобретателите на Световната мрежа са си представяли нейното използване, като прочетете повече за историята ѝ. Някои полезни сайтове включват:
[История на уеб браузърите](https://www.mozilla.org/firefox/browsers/browser-history/)
[История на уеб](https://webfoundation.org/about/vision/history-of-the-web/)
[Интервю с Тим Бърнърс-Ли](https://www.theguardian.com/technology/2019/mar/12/tim-berners-lee-on-30-years-of-the-web-if-we-dream-a-little-we-can-get-the-web-we-want)
### ⚡ **Какво можете да направите през следващите 5 минути**
- [ ] Отворете страницата с разширения на Chrome/Edge (chrome://extensions) и разгледайте инсталираните разширения
- [ ] Разгледайте раздела Network в DevTools на браузъра си докато зареждате уеб страница
- [ ] Опитайте да видите източника на страницата (Ctrl+U), за да видите HTML структурата
- [ ] Инспектирайте всеки елемент на уеб страницата и модифицирайте CSS в DevTools
### 🎯 **Какво можете да постигнете този час**
- [ ] Завършете пост-урочния квиз и разберете основите на браузъра
- [ ] Създайте базов manifest.json файл за браузърно разширение
- [ ] Постройте просто разширение "Hello World" с изскачащ прозорец
- [ ] Тествайте зареждането на разширението в режим разработчик
- [ ] Разгледайте документацията за разширенията на таргетирания браузър
### 📅 **Вашето пътешествие с разширения през седмицата**
- [ ] Завършете функционално браузърно разширение с реална полезност
- [ ] Научете за content scripts, background scripts и popup взаимодействия
- [ ] Овладейте браузърни API-та като storage, tabs и messaging
- [ ] Проектирайте потребителски приятелски интерфейси за разширението
- [ ] Тествайте разширението върху различни сайтове и сценарии
- [ ] Публикувайте разширението в магазина за браузърни разширения
### 🌟 **Вашето месечно развитие на браузърни приложения**
- [ ] Създайте множество разширения, които решават различни потребителски проблеми
- [ ] Научете напреднали браузърни API-та и най-добри практики за сигурност
- [ ] Допринасяйте в проекти за отворен код за браузърни разширения
- [ ] Овладейте кръстосана съвместимост между браузъри и прогресивно подобрение
- [ ] Създавайте инструменти и шаблони за разработка на разширения за други разработчици
- [ ] Станете експерт по браузърни разширения, който подпомага други разработчици
## 🎯 Вашият график за овладяване на браузърни разширения
```mermaid
timeline
title Развитие на разширение за браузър
section Основи (15 минути)
Разбиране на браузъра: Основна архитектура
: Процес на рендериране
: Точки за интеграция на разширенията
section Настройка (20 минути)
Среда за разработка: Структура на проекта
: Конфигурация на инструменти за билд
: Режим на разработчик в браузъра
: Процес на зареждане на разширението
section Дизайн на интерфейса (25 минути)
Потребителски опит: HTML структура
: CSS стилизиране
: Валидация на формите
: Отзивчив дизайн
section Основна функционалност (35 минути)
Интеграция на JavaScript: Обработка на събития
: Взаимодействия с API
: Съхранение на данни
: Обработка на грешки
section API на браузъра (45 минути)
Интеграция на платформата: Система за разрешения
: API за съхранение
: Управление на разделите
: Контекстни менюта
section Разширени функции (1 седмица)
Професионални разширения: Скриптове за заден план
: Скриптове за съдържание
: Съвместимост между браузъри
: Оптимизация на производителността
section Публикуване (2 седмици)
Разпространение: Подаване в магазина
: Процес на преглед
: Обратна връзка от потребителите
: Управление на актуализации
section Експертно ниво (1 месец)
Екосистема на разширенията: Разширени API
: Най-добри практики за сигурност
: Функции за предприятия
: Интеграция с рамки
```
### 🛠️ Обобщение на вашия набор от инструменти за разработка на разширение
След като завършихте този урок, вече имате:
- **Знания за архитектура на браузъра**: Разбиране на рендеринг двигателя, модели за сигурност и интеграция на разширения
- **Работна среда за разработка**: Модерен инструментариум с Webpack, NPM и възможности за дебъгване
- **Основи на UI/UX**: Семантична HTML структура с модели за прогресивно разкриване
- **Осъзнатост за сигурността**: Разбиране на разрешенията на браузъра и практики за безопасна разработка
- **Концепции за крос-браузърност**: Знания за съвместимост и подходи за тестване
- **Интеграция на API-та**: Основа за работа с външни източници на данни
- **Професионален работен процес**: Стандартизирани процедури за разработка и тестване
**Приложения в реалния свят**: Тези умения са приложими директно за:
- **Уеб разработка**: Едно-странични приложения и прогресивни уеб приложения
- **Десктоп приложения**: Electron и уеб-базирани десктоп софтуери
- **Мобилна разработка**: Хибридни приложения и уеб-базирани мобилни решения
- **Корпоративни инструменти**: Вътрешни приложения за продуктивност и автоматизация на работни процеси
- **Отворен код**: Участие в проекти за браузърни разширения и уеб стандарти
**Следващо ниво**: Готови сте да добавите интерактивна функционалност, да работите с браузърни API-та и да създавате разширения, решаващи истински потребителски нужди!
## Задача
[Преоформете своето разширение](assignment.md)
---
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Отказ от отговорност**:
Този документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.
Този документ е преведен с помощта на AI преводна услуга [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Не носим отговорност за всякакви недоразумения или неправилни тълкувания, произтичащи от използването на този превод.
Спомняте ли си браузърното разширение, което започнахте да изграждате? В момента имате добре изглеждаща форма, но тя е по същество статична. Днес ще я оживим, като я свържем с реални данни и й дадем памет.
Помислете за компютрите за управление на мисията "Аполо" - те не просто показваха фиксирана информация. Те постоянно комуникираха с космическия кораб, актуализираха данни за телеметрията и запомняха критични параметри на мисията. Това е видът динамично поведение, което ще изградим днес. Вашето разширение ще се свърже с интернет, ще извлече реални данни за околната среда и ще запомни вашите настройки за следващия път.
Интеграцията с API може да звучи сложно, но всъщност е просто обучение на вашия код как да комуникира с други услуги. Независимо дали извличате данни за времето, социални медии или информация за въглеродния отпечатък, както ще направим днес, всичко се свежда до установяване на тези цифрови връзки. Ще разгледаме и как браузърите могат да запазват информация - подобно на това как библиотеките използват каталози с карти, за да запомнят къде се намират книгите.
До края на този урок ще имате браузърно разширение, което извлича реални данни, съхранява потребителски предпочитания и предоставя гладко изживяване. Да започваме!
✅ Следвайте номерираните сегменти в съответните файлове, за да знаете къде да поставите вашия код.
# Browser Extension Project Part 2: Call an API, use Local Storage
```mermaid
journey
title Вашето пътуване с интеграция и съхранение на API
Помните ли разширението за браузър, което започнахте да изграждате? В момента имате хубава форма, но тя всъщност е статична. Днес ще я вдъхнем живот, като я свържем с реални данни и ѝ дадем памет.
Помислете за компютрите в контролната зала на мисията Аполо – те не просто показваха фиксирана информация. Те постоянно комуникираха с космическите кораби, актуализираха сес телеметрични данни и помнеха критични параметри на мисията. Това е видът динамично поведение, което изграждаме днес. Вашето разширение ще се свързва с интернет, ще извлича реални екологични данни и ще помни вашите настройки за следващия път.
Интеграцията с API може да звучи сложно, но на практика това е просто да научите кода си как да комуникира с други услуги. Независимо дали извличате данни за времето, социални медии или информация за въглеродния отпечатък, както ще правим днес, целта е да създадете тези дигитални връзки. Ще проучим също как браузърите могат да запазват информация – подобно на картотеките в библиотеките, които помнят къде принадлежат книгите.
До края на този урок ще имате разширение за браузър, което извлича реални данни, съхранява предпочитания на потребителя и осигурява гладко преживяване. Да започваме!
```mermaid
mindmap
root((Динамични Разширения))
DOM Manipulation
Избор на Елемент
Обработка на Събития
Управление на Състоянието
Актуализации на Потребителския Интерфейс
Local Storage
Запазване на Данни
Ключ-Стойност Двойки
Управление на Сесии
Потребителски Настройки
API Integration
HTTP Заявки
Автентикация
Парсиране на Данни
Обработка на Грешки
Async Programming
Обещания
Async/Await
Улавяне на Грешки
Некопиращ Код
User Experience
Зареждащи Състояния
Съобщения за Грешки
Плавни Преходи
Валидация на Данни
```
✅ Следвайте номерираните сегменти в съответните файлове, за да знаете къде да поставите кода си
## Настройка на елементите за манипулиране в разширението
Преди вашият JavaScript да може да манипулира интерфейса, той трябва да има препратки към конкретни HTML елементи. Помислете за това като за телескоп, който трябва да бъде насочен към определени звезди - преди Галилей да може да изучава луните на Юпитер, той трябваше да локализира и фокусира върху самия Юпитер.
Във вашия файл `index.js` ще създадем променливи `const`, които улавят препратки към всеки важен елемент от формата. Това е подобно на начина, по който учените маркират своето оборудване - вместо да търсят из цялата лаборатория всеки път, те могат директно да достъпят това, което им е необходимо.
Преди вашият JavaScript да може да манипулира интерфейса, той има нужда от препратки към конкретни HTML елементи. Помислете за това като за телескоп, който трябва да се насочи към определени звезди – преди Галилео да изучава спътниците на Юпитер, той трябваше да открие и фокусира самия Юпитер.
Във вашия файл `index.js` ще създадем `const` променливи, които записват препратки към всеки важен елемент от формата. Това е подобно на начина, по който учените етикетират оборудването си – вместо да търсят из цялата лаборатория всеки път, могат директно да достъпват това, което им трябва.
```mermaid
flowchart LR
A[Код на JavaScript] --> B[document.querySelector]
B --> C[CSS селектори]
C --> D[HTML елементи]
D --> E[".form-data"]
D --> F[".region-name"]
D --> G[".api-key"]
D --> H[".loading"]
D --> I[".errors"]
D --> J[".result-container"]
E --> K[Формулярен елемент]
F --> L[Поле за въвеждане]
G --> M[Поле за въвеждане]
H --> N[Потребителски интерфейс]
I --> O[Потребителски интерфейс]
J --> P[Потребителски интерфейс]
style A fill:#e1f5fe
style D fill:#e8f5e8
style K fill:#fff3e0
style L fill:#fff3e0
style M fill:#fff3e0
```
```javascript
// form fields
// полета на формуляра
const form = document.querySelector('.form-data');
const region = document.querySelector('.region-name');
- **Улавя** елементи от формата, използвайки `document.querySelector()`с CSS клас селектори
- **Създава** препратки към полетата за въвеждане на име на регион и API ключ
- **Установява** връзки към елементи за показване на резултати за данни за въглеродна употреба
- **Настройва** достъп до елементи на потребителския интерфейс като индикатори за зареждане и съобщения за грешки
- **Съхранява** всяка препратка към елемент в променлива `const` за лесно повторно използване в целия код
## Добавяне на слушатели за събития
Сега ще направим вашето разширение да реагира на действията на потребителя. Слушателите за събития са начинът, по който вашият код следи взаимодействията на потребителя. Помислете за тях като за операторите в ранните телефонни централи - те слушаха входящите обаждания и свързваха правилните линии, когато някой искаше да направи връзка.
- **Записва** елементи от формата чрез `document.querySelector()`с CSS селектори по класове
- **Създава** препратки към полета за въвеждане за името на региона и API ключа
- **Установява** връзки към елементи за показване на резултати с данни за използване на въглерод
- **Настройва** достъп до UI елементи като индикатори за зареждане и съобщения за грешки
- **Съхранява** всяка препратка в `const` променлива за лесно повторно използване в целия ви код
## Добавяне на слушатели на събития
Сега ще накараме разширението ви да реагира на действия от потребителя. Слушателите на събития са начинът, по който кодът ви наблюдава взаимодействията на потребителя. Помислете за тях като за операторите в ранните телефонни централи – те слушаха входящи повиквания и свързваха правилните вериги, когато някой искаше да осъществи връзка.
- **Прикрепя** слушател за изпращане към формата, който се задейства, когато потребителите натиснат Enter или кликнат върху изпращане
- **Свързва** слушател за клик към бутона за изчистване за нулиране на формата
- **Предава** обекта на събитието `(e)` към функции за обработка за допълнителен контрол
- **Извиква** функцията `init()` незабавно, за да настрои началното състояние на вашето разширение
- **Прикачва** слушател за „submit“ към формата, който се задейства, когато потребителите натиснат Enter или изпратят формата
- **Свързва** слушател за „click“ към бутона за изчистване, за нулиране на формата
- **Пуска** обекта на събитието `(e)` към обработващите функции за допълнителен контрол
- **Извиква** функцията `init()` веднага, за да настрои началното състояние на разширението
✅ Обърнете внимание на съкратения синтаксис с функционален стрелков израз (arrow function), използван тук. Този модерен JavaScript подход е по-четим от традиционните изрази с функции, но и двата работят еднакво добре!
✅ Обърнете внимание на съкратения синтаксис на стрелковите функции, използван тук. Този модерен подход в JavaScript е по-чист от традиционните изрази на функции, но и двата работят еднакво добре!
### 🔄 **Педагогическа проверка**
**Разбиране на обработката на събития**: Преди да преминете към инициализацията, уверете се, че можете да:
- ✅ Обясните как `addEventListener` свързва действията на потребителя с JavaScript функции
- ✅ Разберете защо подаваме обекта на събитието `(e)` към обработващите функции
- ✅ Разпознаете разликата между събитията `submit` и `click`
- ✅ Описвате кога се изпълнява функцията `init()` и защо
## Създаване на функции за инициализация и нулиране
**Бърз тест за себе си**: Какво би се случило, ако забравите `e.preventDefault()` при изпращане на формата?
*Отговор: Страницата ще се презареди, което ще загуби цялото състояние на JavaScript и ще прекъсне потребителското преживяване*
Нека създадем логиката за инициализация на вашето разширение. Функцията `init()`е като навигационната система на кораб, която проверява своите инструменти - тя определя текущото състояние и съответно настройва интерфейса. Тя проверява дали някой е използвал вашето разширение преди и зарежда предишните му настройки.
## Изграждане на функциите за инициализация и нулиране
Функцията `reset()` предоставя на потребителите ново начало - подобно на това как учените нулират своите инструменти между експерименти, за да осигурят чисти данни.
Нека създадем логиката за инициализация на вашето разширение. Функцията `init()`е като навигационната система на кораб, която проверява инструментите си – тя определя текущото състояние и настройва интерфейса според него. Проверява дали някой е използвал разширението преди и зарежда предишните му настройки.
Функцията `reset()` дава на потребителя нов старт – подобно на това как учените нулират инструментите си между експерименти, за да осигурят чисти данни.
```javascript
function init() {
// Check if user has previously saved API credentials
// Проверете дали потребителят е запазил API данни преди
// Set extension icon to generic green (placeholder for future lesson)
// TODO: Implement icon update in next lesson
// Задайте иконата на разширението на общ зелен цвят (заместител за бъдещ урок)
// TODO: Имплементирайте обновяване на иконата в следващия урок
if (storedApiKey === null || storedRegion === null) {
// First-time user: show the setup form
// Потребител за първи път: покажете формата за настройка
form.style.display = 'block';
results.style.display = 'none';
loading.style.display = 'none';
clearBtn.style.display = 'none';
errors.textContent = '';
} else {
// Returning user: load their saved data automatically
// Връщащ се потребител: заредете автоматично запазените му данни
displayCarbonUsage(storedApiKey, storedRegion);
results.style.display = 'none';
form.style.display = 'none';
@ -105,49 +208,72 @@ function init() {
function reset(e) {
e.preventDefault();
// Clear stored region to allow user to choose a new location
// Изчистете запазения регион, за да позволите на потребителя да избере ново място
localStorage.removeItem('regionName');
// Restart the initialization process
// Рестартирайте процеса на инициализация
init();
}
```
**Разбивка на случващото се тук:**
- **Извлича** съхранения API ключ и регион от локалното съхранение на браузъра
- **Проверява** дали това е първият път, когато потребителят използва разширението (няма съхранени данни) или е завръщащ се потребител
**Разграждане на случващото се тук:**
- **Извлича** запазения API ключ и регион от локалното хранилище на браузъра
- **Проверява** дали това е първократен потребител (без запазени данни) или връщащ се
- **Показва** формата за настройка за нови потребители и скрива други елементи на интерфейса
- **Зарежда** автоматично запазените данни за завръщащисе потребители и показва опцията за нулиране
- **Управлява** състоянието на потребителския интерфейс въз основа на наличните данни
- **Автоматично зарежда** запазените данни за връщащитесе потребители и показва опцията за нулиране
- **Управлява** състоянието на потребителския интерфейс в зависимост от наличните данни
**Основни концепции за локалното съхранение:**
- **Запазва** данни между сесиите на браузъра (за разлика от session storage)
- **Съхранява** данни като двойки ключ-стойност, използвайки`getItem()` и `setItem()`
**Основни понятия за Local Storage:**
- **Запазва** данните между сесиите на браузъра (за разлика от session storage)
- **Съхранява** данните като ключ-стойност с помощта на`getItem()` и `setItem()`
- **Връща** `null`, когато няма данни за даден ключ
- **Осигурява** прост начин за запомняне на потребителски предпочитания и настройки
- **Осигурява** лесен начин за запомняне на предпочитанията и настройките на потребителя
> 💡 **Разбиране на съхранението в браузъра**: [LocalStorage](https://developer.mozilla.org/docs/Web/API/Window/localStorage) е като да дадете на вашето разширение постоянна памет. Помислете как древната библиотека в Александрия е съхранявала свитъци - информацията остава достъпна, дори когато учените напускат и се връщат.
> 💡 **Разбиране на браузърното съхранение**: [LocalStorage](https://developer.mozilla.org/docs/Web/API/Window/localStorage) е като предоставяне на разширението ви постоянна памет. Помислете как древната Александрийска библиотека съхранявала свитъци – информацията оставала налична, дори когато учените напускаха и после се връщаха.
>
> **Основни характеристики:**
> - **Запазва** данни дори след затваряне на браузъра
> - **Оцелява** след рестартиране на компютъра и сривове на браузъра
> - **Осигурява** значително пространство за съхранение на потребителски предпочитания
> - **Предоставя** незабавен достъп без забавяне от мрежата
> **Важно уточнение**: Вашето браузърно разширение има собствено изолирано локално съхранение, което е отделено от обикновените уеб страници. Това осигурява сигурност и предотвратява конфликти с други уебсайтове.
Можете да видите съхранените данни, като отворите инструментите за разработчици на браузъра (F12), отидете на раздела **Application** и разширите секцията **Local Storage**.

> - **Запазва** данните и след като затворите браузъра
> - **Устойчива** на рестартиране на компютъра и сривове на браузъра
> - **Осигурява** значително пространство за съхранение на предпочитания
> - **Предлага** бърз достъп без мрежови закъснения
> **Важно:** Вашето браузърно разширение има собствено изолирано локално хранилище, отделно от редовните уебстраници. Това осигурява сигурност и предотвратява конфликти с други сайтове.
Можете да разглеждате съхранените данни чрез отваряне на инструменти за разработчици в браузъра (F12), навигация до таба **Application** и разширяване на секцията **Local Storage**.
```mermaid
stateDiagram-v2
[*] --> CheckStorage: Разширението стартира
CheckStorage --> FirstTime: Няма запазени данни
CheckStorage --> Returning: Намерени данни
FirstTime --> ShowForm: Показване на формуляр за настройка
ShowForm --> UserInput: Потребителят въвежда данни
UserInput --> SaveData: Запис в localStorage
SaveData --> FetchAPI: Вземане на данни за въглерода
Returning --> LoadData: Четене от localStorage
LoadData --> FetchAPI: Вземане на данни за въглерода
> ⚠️ **Съображения за сигурност**: В производствени приложения съхранението на API ключове в LocalStorage представлява риск за сигурността, тъй като JavaScript може да достъпи тези данни. За учебни цели този подход е подходящ, но реалните приложения трябва да използват сигурно съхранение на сървър за чувствителни данни.
> ⚠️ **Съображения за сигурността**: В продукционни приложения съхраняването на API ключове в LocalStorage представлява риск за сигурността, защото JavaScript може да има достъп до тези данни. За учебни цели този подход е приемлив, но реалните приложения трябва да използват защитено сървърно съхранение за чувствителни данни.
## Обработка на изпращане на форма
## Обработка на изпращане на формата
Сега ще обработим какво се случва, когато някой изпрати вашата форма. По подразбиране браузърите презареждат страницата при изпращане на форми, но ние ще прихванем това поведение, за да създадем по-гладко изживяване.
Сега ще обработим какво се случва при изпращане на вашата форма. По подразбиране браузърите презареждат страницата при изпращане на формуляри, но ние ще прекъснем това поведение, за да осигурим по-гладко преживяване.
Този подход е подобен на начина, по който центърът за управление на мисии обработва комуникациите със космически кораби - вместо да рестартира цялата система за всяко предаване, те поддържат непрекъсната работа, докато обработват нова информация.
Този подход е подобен на начина, по който контролната зала управлява комуникацията с космическите кораби – вместо да нулират цялата система при всяка трансмисия, те поддържат непрекъсната работа, докато обработват новата информация.
Създайте функция, която улавя събитието за изпращане на форма и извлича въведените от потребителя данни:
Създайте функция, която хваща събитието за изпращане на формата и извлича въведените от потребителя данни:
```javascript
function handleSubmit(e) {
@ -156,93 +282,148 @@ function handleSubmit(e) {
}
```
**В горното сме:**
- **Предотвратява** стандартното поведение при изпращане на форма, което би презаредило страницата
- **Извлича** стойности, въведени от потребителя, от полетата за API ключ и регион
- **Предава** данните от формата към функцията `setUpUser()` за обработка
- **Поддържа** поведение на приложение с една страница, като избягва презареждането на страницата
**По-горе сме:**
- **Предотвратили** стандартното поведение на изпращане на формата, което иначе би презаредило страницата
- **Извлекли** стойностите на потребителския вход от полетата за API ключ и регион
- **Подали** формулярните данни към функцията `setUpUser()` за обработка
- **Поддържали** поведението на SPA (single-page application) чрез избягване на презареждане
✅ Запомнете, че вашите HTML полета за форма включват атрибута `required`, така че браузърът автоматично валидира, че потребителите предоставят както API ключ, така и регион, преди тази функция да се изпълни.
✅ Помнете, че HTML полетата във вашата форма съдържат атрибута `required`, така че браузърът автоматично проверява дали API ключът и регионът са предоставени, преди тази функция да се изпълни.
## Настройка на потребителски предпочитания
## Настройване на потребителските предпочитания
Функцията `setUpUser`е отговорна за запазването на потребителските данни и инициирането на първото API извикване. Това създава плавен преход от настройката към показването на резултати.
Функцията `setUpUser`отговаря за запазване на данните на потребителя и стартира първото извикване на API. Това създава плавен преход от настройка към показване на резултати.
```javascript
function setUpUser(apiKey, regionName) {
// Save user credentials for future sessions
// Запазване на потребителските данни за следващи сесии
localStorage.setItem('apiKey', apiKey);
localStorage.setItem('regionName', regionName);
// Update UI to show loading state
// Актуализирайте интерфейса за показване на състоянието на зареждане
loading.style.display = 'block';
errors.textContent = '';
clearBtn.style.display = 'block';
// Fetch carbon usage data with user's credentials
// Вземете данни за използването на въглерод с потребителските данни
displayCarbonUsage(apiKey, regionName);
}
```
**Стъпка по стъпка, ето какво се случва:**
- **Запазва** API ключа и името на региона в локалното съхранение за бъдеща употреба
- **Показва** индикатор за зареждане, за да информира потребителите, че данните се извличат
- **Изчиства** всички предишни съобщения за грешки от дисплея
- **Разкрива** бутона за изчистване, за да могат потребителите да нулират своите настройки по-късно
- **Инициира** API извикването за извличане на реални данни за въглеродна употреба
Тази функция създава безпроблемно потребителско изживяване, като управлява както запазването на данни, така и актуализациите на потребителския интерфейс в едно координирано действие.
## Показване на данни за въглеродна употреба
Сега ще свържем вашето разширение с външни източници на данни чрез API. Това трансформира вашето разширение от самостоятелен инструмент в нещо, което може да получава информация в реално време от интернет.
**Разбиране на API**
[API](https://www.webopedia.com/TERM/A/API.html) са начинът, по който различни приложения комуникират помежду си. Помислете за тях като за телеграфната система, която свързва отдалечени градове през 19-ти век - операторите изпращаха заявки до отдалечени станции и получаваха отговори с исканата информация. Всеки път, когато проверявате социални медии, задавате въпрос на гласов асистент или използвате приложение за доставка, API улесняват тези обмен на данни.
**Основни концепции за REST API:**
- **REST** означава "Представително състояние на трансфер"
**Стъпка по стъпка се случва:**
- **Записва** API ключа и името на региона в локалното хранилище за по-късна употреба
- **Показва** индикатор за зареждане, за да информира потребителите, че данни се извличат
- **Изчиства** всякакви предишни съобщения за грешки от дисплея
- **Показва** бутона за изчистване, за да могат потребителите да нулират настройките си по-късно
- **Инициира** извикване на API за получаване на реални данни за използване на въглерод
Тази функция създава безпроблемно потребителско преживяване, като управлява както съхранението на данни, така и актуализацията на интерфейса в едно координирано действие.
## Показване на данни за използване на въглерод
Сега ще свържем разширението ви с външни източници на данни чрез API-та. Това превръща разширението ви от самостоятелен инструмент в нещо, което може да достъпва актуална информация от интернет.
**Разбиране на API-та**
[API-тата](https://www.webopedia.com/TERM/A/API.html) са начинът, по който различните приложения комуникират помежду си. Помислете ги като телеграфната система от 19-ти век, която свързвала отдалечени градове – операторите изпращали заявки до далечни станции и получавали отговори с исканата информация. Всеки път, когато проверявате социални медии, питате гласов асистент или използвате приложение за доставка, API-тата осъществяват тези обмен на данни.
```mermaid
flowchart TD
A[Вашето разширение] --> B[HTTP заявка]
B --> C[CO2 Signal API]
C --> D{Валидна заявка?}
D -->|Да| E[Запитване в база данни]
D -->|Не| F[Връщане на грешка]
E --> G[Данни за въглерод]
G --> H[JSON отговор]
H --> I[Вашето разширение]
F --> I
I --> J[Актуализиране на интерфейса]
subgraph "API заявка"
K[Хедъри: auth-token]
L[Параметри: countryCode]
M[Метод: GET]
end
subgraph "API отговор"
N[Интензивност на въглерода]
O[% на изкопаеми горива]
P[Отпечатък на времето]
end
style C fill:#e8f5e8
style G fill:#fff3e0
style I fill:#e1f5fe
```
**Основни понятия за REST API:**
- **REST** означава "Representational State Transfer"
- **Използва** стандартни HTTP методи (GET, POST, PUT, DELETE) за взаимодействие с данни
- **Връща** данни в предвидими формати, обикновено JSON
- **Осигурява** последователни, базирани на URL крайни точки за различни типове заявки
- **Осигурява** стабилни, базирани на URL крайни точки за различни видове заявки
✅ [CO2 Signal API](https://www.co2signal.com/), който ще използваме, предоставя данни за въглеродната интензивност на електрическите мрежи по целия свят в реално време. Това помага на потребителите да разберат екологичния отпечатък на тяхното електрическо потребление!
✅ [API-то CO2 Signal](https://www.co2signal.com/), което ще ползваме, предоставя данни в реално време за въглеродната интензивност на електроенергията по света. Това помага на потребителите да разберат екологичния ефект от използването на електричество!
> 💡 **Разбиране на асинхронния JavaScript**: [`async` ключовата дума](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function) позволява на вашия код да обработва множество операции едновременно. Когато поискате данни от сървър, не искате цялото разширение да замръзне - това би било като въздушен контрол, който спира всички операции, докато чака един самолет да отговори.
> 💡 **Разбиране на асинхронния JavaScript**: Ключовата дума [`async`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/async_function) позволява на кода ви да управлява множество операции едновременно. Когато искате данни от сървър, не искате цялото разширение да се "замразява" – това би било като въздушен контрол, който спира всички операции, докато един самолет отговори.
>
> **Основни предимства:**
> - **Поддържа** отзивчивостта на разширението, докато данните се зареждат
> - **Позволява** на друг код да продължи да се изпълнява по време на мрежови заявки
> - **Подобрява** четимостта на кода в сравнение с традиционните модели на обратни обаждания
> - **Позволява** елегантно обработване на грешки при мрежови проблеми
> - **Поддържа** отзивчивост на разширението докато зареждат данни
> - **Позволява** друг код да продължи да се изпълнява докато има мрежови заявки
> - **Подобрява** четимостта на кода спрямо традиционните callback модели
> - **Позволява** гладко обработване на грешки при мрежови проблеми
Ето кратко видео за `async`:
[](https://youtube.com/watch?v=YwmlRkrxvkk "Async и Await за управление на обещания")
[](https://youtube.com/watch?v=YwmlRkrxvkk "Async and Await for managing promises")
> 🎥 Кликнете върху изображението по-горе за видео за async/await.
Създайте функцията за извличане и показване на данни за въглеродна употреба:
### 🔄 **Педагогическа проверка**
**Разбиране на асинхронното програмиране**: Преди да се потопите във функцията за API, уверете се, че разбирате:
- ✅ Защо използваме `async/await` вместо блокиране на цялото разширение
- ✅ Как блоковете `try/catch` обработват мрежовите грешки плавно
- ✅ Разликата между синхронни и асинхронни операции
- ✅ Защо API повикванията могат да се провалят и как да се справите с тези провали
**Реални връзки**: Помислете за тези всекидневни async примери:
- **Поръчване на храна**: Не чакате в кухнята – получавате бележка и продължавате други дейности
- **Изпращане на имейли**: Приложението не замръзва при изпращане – можете да пишете още имейли
- **Зареждане на уеб страници**: Картинките се зареждат постепенно, докато вече можете да четете текста
**Поток на API автентикация**:
```mermaid
sequenceDiagram
participant Ext as Разширение
participant API as CO2 Signal API
participant DB as База данни
Ext->>API: Заявка с auth-token
API->>API: Валидация на токен
API->>DB: Запитване за въглеродни данни
DB->>API: Връщане на данни
API->>Ext: JSON отговор
Ext->>Ext: Обновяване на интерфейса
```
Създайте функцията за извличане и показване на данни за използването на въглерод:
```javascript
// Modern fetch API approach (no external dependencies needed)
// Съвременен подход с fetch API (без външни зависимости)
async function displayCarbonUsage(apiKey, region) {
try {
// Fetch carbon intensity data from CO2 Signal API
// Извличане на данни за интензивност на въглерода от CO2 Signal API
// Показване на удобен за потребителя съобщение за грешка
loading.style.display = 'none';
results.style.display = 'none';
errors.textContent = 'Sorry, we couldn\'t fetch data for that region. Please check your API key and region code.';
@ -274,46 +455,209 @@ async function displayCarbonUsage(apiKey, region) {
}
```
**Разбивка на случващото се тук:**
- **Използва** модерния `fetch()` API вместо външни библиотеки като Axios за по-чист код без зависимости
- **Прилага** правилна проверка за грешки с`response.ok`, за да улови ранни неуспехи на API
- **Обработва** асинхронни операции с`async/await` за по-четим поток на кода
- **Автентифицира** с CO2 Signal API, използвайки заглавката `auth-token`
- **Парсира** JSON отговори и извлича информация за въглеродната интензивност
- **Актуализира** множество елементи на потребителския интерфейс с форматирани данни за околната среда
- **Осигурява** удобни за потребителя съобщения за грешки, когато API заявките се провалят
**Основни модерни концепции в JavaScript:**
- **Шаблонни литерали** със синтаксис `${}` за чисто форматиране на текст
- **Обработка на грешки** с try/catch блокове за надеждни приложения
- **Async/await** модел за елегантно управление на мрежови заявки
- **Деструктуриране на обекти** за извличане на специфични данни от API отговори
- **Верижно свързване на методи** за множество манипулации на DOM
✅ Тази функция демонстрира няколко важни концепции за уеб разработка - комуникация с външни сървъри, обработка на автентификация, обработка на данни, актуализиране на интерфейси и елегантно управление на грешки. Това са основни умения, които професионалните разработчици използват редовно.
Тествайте вашата работа, като изпълните `npm run build` и обновите вашето разширение в браузъра. Сега имате функционален тракер за въглеродния отпечатък. В следващия урок ще добавим функционалност за динамични икони, за да завършим разширението.
**Разграждане на случващото се тук:**
- **Използва** модерния API `fetch()`, вместо външни библиотеки като Axios, за по-чист код без зависимости
- **Прилага** правилна проверка за грешки с`response.ok` за ранно засичане на откази на API
- **Обработва** асинхронни операции с`async/await` за по-четлив ход на кода
- **Автентикира** с CO2 Signal API чрез хедъра `auth-token`
- **Парсира** JSON данните от отговора и извлича информация за въглеродната интензивност
- **Обновява** няколко UI елемента с форматирана екологична информация
- **Осигурява** потребителски разбираеми съобщения за грешки при провали на API повиквания
**Основни модерни JavaScript концепции:**
- **Template literals**с`${}` синтаксис за чисто форматиране на низове
- **Обработка на грешки** с try/catch блокове за стабилни приложения
- **Async/await** модел за плавно управление на мрежови заявки
- **Деструктуриране на обекти** за извличане на конкретни данни от отговори
- **Верижно извикване** за множество манипулации на DOM
✅ Тази функция демонстрира няколко важни концепции при уеб разработка – комуникация с външни сървъри, управление на автентикация, обработка на данни, обновяване на интерфейса и държане на грешки под контрол. Това са фундаментални умения, с които професионалните разработчици работят постоянно.
```mermaid
flowchart TD
A[Стартиране на API повикване] --> B[Извличане на заявка]
B --> C{Мрежата успешна?}
C -->|Не| D[Мрежова грешка]
C -->|Да| E{Отговорът ОК?}
E -->|Не| F[Грешка в API]
E -->|Да| G[Парсиране на JSON]
G --> H{Валидни данни?}
H -->|Не| I[Грешка с данните]
H -->|Да| J[Обновяване на UI]
D --> K[Показване на съобщение за грешка]
F --> K
I --> K
J --> L[Скриване на зареждането]
K --> L
style A fill:#e1f5fe
style J fill:#e8f5e8
style K fill:#ffebee
style L fill:#f3e5f5
```
### 🔄 **Педагогическа проверка**
**Пълно разбиране на системата**: Уверете се, че овладявате целия поток:
- ✅ Как препратките към DOM позволяват на JavaScript да контролира интерфейса
- ✅ Защо локалното хранилище осигурява постоянство между сесиите на браузъра
- ✅ Как async/await прави API повиквания без да замразява разширението
- ✅ Какво се случва при провал на API повиквания и как се обработват грешките
- ✅ Защо потребителското преживяване включва състояния за зареждане и съобщения за грешки
- **Свързва** сес интернет и извлича реални екологични данни
- **Запазва** потребителските настройки между сесиите
- **Обработва** грешки без сривове
- **Осигурява** плавно и професионално потребителско изживяване
Тествайте работата си, като стартирате `npm run build` и обновите разширението в браузъра. Сега имате функционален тракер за въглероден отпечатък. Следващият урок ще добави динамична иконка, за да завърши разширението.
---
## Предизвикателство с GitHub Copilot Agent 🚀
Използвайте режима Agent, за да изпълните следното предизвикателство:
**Описание:** Подобрете браузърното
В този урок научихте за LocalStorage и API-та, и двете са много полезни за професионалния уеб разработчик. Можете ли да помислите как тези две неща работят заедно? Помислете как бихте проектирали уеб сайт, който съхранява елементи, които да бъдат използвани от API.
## GitHub Copilot Agent Challenge 🚀
Използвайтережим Agent, за да изпълните следното предизвикателство:
**Описание:** Подобрете разширението за браузър, като добавите подобрения в управлението на грешки и функции за по-добро потребителско изживяване. Това предизвикателство ще ви помогне да упражните работа с API, локално съхранение и манипулация на DOM, използвайки съвременни JavaScript подходи.
**Задача:** Създайте разширена версия на функцията displayCarbonUsage, която включва: 1) Механизъм за повторен опит при неуспешни API заявки с експоненциално забавяне, 2) Валидация на входа за регионален код преди извършване на API заявката, 3) Анимация за зареждане с индикатори за напредъка, 4) Кеширане на отговорите от API в localStorage с времеви марки за изтичане (кеширане за 30 минути) и 5) Функция за показване на исторически данни от предишни API повиквания. Също така добавете подходящи JSDoc коментари в стила на TypeScript за документиране на всички параметри на функцията и типове на връщаните стойности.
Научете повече за [режим агент](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
## 🚀 Предизвикателство
Разширете знанията си за API, като изследвате богатството от браузър-базирани API, достъпни за уеб разработка. Изберете един от тези браузър API-та и създайте малка демонстрация:
- [Geolocation API](https://developer.mozilla.org/docs/Web/API/Geolocation_API) - Вземете текущото местоположение на потребителя
- [HTML Drag and Drop API](https://developer.mozilla.org/docs/Web/API/HTML_Drag_and_Drop_API) - Създайте интерактивни интерфейси за плъзгане
- [Web Storage API](https://developer.mozilla.org/docs/Web/API/Web_Storage_API) - Разширени техники за локално съхранение
- [Fetch API](https://developer.mozilla.org/docs/Web/API/Fetch_API) - Съвременна алтернатива на XMLHttpRequest
**Изследователски въпроси за разглеждане:**
- Какви реални проблеми решава този API?
- Как API-то се справя с грешки и гранични случаи?
- Какви са съображенията за сигурност при използването на този API?
- Колко широко е поддържан този API в различните браузъри?
След вашето изследване, определете какви характеристики правят един API удобен за разработчици и надежден.
## Викторина след лекцията
[Викторина след лекция](https://ff-quizzes.netlify.app/web/quiz/26)
## Преглед и Самостоятелно обучение
Научихте за LocalStorage и API-тата в този урок, които са много полезни за професионалния уеб разработчик. Можете ли да помислите как тези две неща работят заедно? Помислете как бихте архитектурирали уеб сайт, който съхранява елементи, използвани от API.
### ⚡ **Какво можете да направите в следващите 5 минути**
- [ ] Отворете раздела Application в DevTools и разгледайте localStorage на някой уебсайт
- [ ] Създайте прост HTML формуляр и тествайте валидацията му в браузъра
- [ ] Опитайте да съхранявате и извличате данни с localStorage в конзолата на браузъра
- [ ] Прегледайте данните от формуляр, които се изпращат, използвайки раздела Network
### 🎯 **Какво можете да постигнете в този час**
- [ ] Попълнете викторината след урока и разберете концепциите за обработка на формуляри
- [ ] Създайте формуляр за разширение на браузър, който запазва потребителските предпочитания
- [ ] Реализирайте валидация на страна клиент с полезни съобщения за грешки
- [ ] Практикувайте използването на chrome.storage API за съхранение на данни в разширението
- [ ] Създайте потребителски интерфейс, който реагира на съхранените потребителски настройки
### 📅 **Вашето седмично изграждане на разширение**
- [ ] Завършете разширение за браузър с пълна функционалност за формуляри
- [ ] Усъвършенствайте различни опции за съхранение: local, sync и session storage
- [ ] Реализирайте разширени функции за формуляри като автозавършване и валидация
- [ ] Добавете функция за импортиране/експортиране на потребителски данни
- [ ] Тествайте разширението си обстойно в различни браузъри
- [ ] Изгладете потребителското изживяване и управлението на грешки
### 🌟 **Вашето месечно усвояване на уеб API**
- [ ] Изграждайте сложни приложения, използвайки различни API-та за браузърно съхранение
- [ ] Научете за модели за разработка offline-first
- [ ] Допринасяйте за проекти с отворен код, свързани със съхранение на данни
- [ ] Усъвършенстване на разработката със защита на личните данни и съответствие с GDPR
- [ ] Създавайте многократно използваеми библиотеки за обработка на формуляри и управление на данни
- [ ] Споделяйте знания за уеб API-та и разработка на разширения
## 🎯 Вашият времеви график за овладяване на разработката на разширения
```mermaid
timeline
title Напредък в обучението по интеграция на API и съхранение
section Основи на DOM (15 минути)
Елементни препратки: усвояване на querySelector
: Настройка на слушатели за събития
: Основи на управление на състоянието
section Локално съхранение (20 минути)
Запазване на данни: Съхранение ключ-стойност
: Управление на сесията
: Обработка на потребителски предпочитания
: Инструменти за преглед на съхранението
section Обработка на формуляри (25 минути)
Потребителски вход: Валидиране на формуляри
: Предотвратяване на събития
: Извличане на данни
: Преходи в състоянието на интерфейса
section Интеграция на API (35 минути)
Външна комуникация: HTTP заявки
: Модели за удостоверяване
: Парсиране на JSON данни
: Обработка на отговори
section Асинхронно програмиране (40 минути)
Модерен JavaScript: Управление на промиси
: Async/await модели
: Управление на грешки
: Неблокиращи операции
section Обработка на грешки (30 минути)
Здрави приложения: Try/catch блокове
: Потребителски съобщения
: Плавен спад
: Техники за дебъгване
section Разширени модели (1 седмица)
Професионално развитие: Стратегии за кеширане
: Ограничаване на честота
: Механизми за повторение
: Оптимизация на производителността
section Производствени умения (1 месец)
Функции за предприятия: Най-добри практики за сигурност
: Версиониране на API
: Мониторинг и логване
: Скалираща се архитектура
```
### 🛠️ Резюме на вашия инструментариум за Full-Stack разработка
След завършването на този урок вече имате:
- **Владеене на DOM**: Прецизно насочване и манипулация на елементи
- **Експертиза в съхранението**: Управление на устойчиви данни с localStorage
- **Интеграция с API**: Взимане на данни в реално време и удостоверяване
- **Асинхронно програмиране**: Асинхронни операции с модерния JavaScript
- **Обработка на грешки**: Надеждни приложения, които грациозно се справят с повреди
- **Потребителско изживяване**: Състояния на зареждане, валидация и плавни взаимодействия
- **Модерни модели**: fetch API, async/await и ES6+ функции
**Професионални умения, придобити**: Използвали сте модели в:
- **Уеб приложения**: Single-page apps с външни източници на данни
- **Мобилна разработка**: API-зависими приложения с офлайн възможности
- **Настолен софтуер**: Electron приложения с постоянно съхранение
- **Корпоративни системи**: Удостоверяване, кеширане и управление на грешки
- **Модерни рамки**: React/Vue/Angular модели за управление на данни
**Следващо ниво**: Готови сте да изследвате напреднали теми като стратегии за кеширане, WebSocket връзки в реално време или комплексно управление на състояния!
## Задача
[Осиновете API](assignment.md)
[Adopt an API](assignment.md)
---
**Отказ от отговорност**:
Този документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Отказ от отговорност**:
Този документ е преведен с помощта на AI преводаческа услуга [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи могат да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за каквито и да е недоразумения или неправилни тълкувания, произтичащи от използването на този превод.
# Проект за браузър разширение, част 3: Научете за фоновите задачи и производителността
Чудили ли сте се какво прави някои браузър разширения бързи и отзивчиви, докато други изглеждат бавни? Тайната се крие в това, което се случва зад кулисите. Докато потребителите кликат из интерфейса на вашето разширение, има цял свят от фонови процеси, които тихо управляват извличането на данни, актуализациите на иконите и системните ресурси.
# Проект за браузър разширение Част 3: Научете за фонови задачи и производителност
```mermaid
journey
title Вашето пътешествие за оптимизиране на производителността
section Основи
Научете инструменти за браузър: 3: Student
Разберете профилирането: 4: Student
Идентифицирайте тесни места: 4: Student
section Разширителни функции
Създайте цветова система: 4: Student
Създайте задачи на заден план: 5: Student
Актуализирайте иконите динамично: 5: Student
section Оптимизация
Наблюдавайте производителността: 5: Student
Отстранявайте проблеми: 4: Student
Полирайте изживяването: 5: Student
```
Някога чудили ли сте се как някои браузърни разширения изглеждат бързи и отзивчиви, докато други сякаш се забавят? Тайното се крие в това, което се случва зад кадър. Докато потребителите кликат из интерфейса на разширението ви, зад сцената има цял свят от фонови процеси, които тихо управляват извличането на данни, обновяването на иконите и системните ресурси.
Това е последният ни урок от серията за браузър разширения, и ще направим вашия тракер за въглероден отпечатък да работи гладко. Ще добавите динамични актуализации на иконите и ще научите как да откривате проблеми с производителността, преди да се превърнат в проблеми. Това е като настройка на състезателна кола - малките оптимизации могат да направят огромна разлика в начина, по който всичко работи.
Това енашият последен урок в серията за браузърни разширения и ще направим вашия тракер за въглеродния отпечатък да работи гладко. Ще добавите динамично обновяване на иконите и ще научите как да откривате проблеми с производителността преди да станат сериозни. Това е като настройка на състезателна кола - малките оптимизации могат да направят голяма разлика в начина, по който всичко работи.
До края на урока ще имате полирано разширение и ще разберете принципите на производителността, които отличават добрите уеб приложения от страхотните. Нека се потопим в света на оптимизацията на браузъра.
Когато свършим, ще имате полиранo разширение и ще разбирате принципите на производителността, които разделят добрите уеб приложения от страхотните. Нека се гмурнем в света на оптимизацията в браузъра.
## Тест преди лекцията
## Предварителен квиз
[Тест преди лекцията](https://ff-quizzes.netlify.app/web/quiz/27)
В предишните ни уроци създадохте форма, свързахте я с API и се справихте с асинхронното извличане на данни. Вашето разширение се оформя добре.
Сега трябва да добавим последните щрихи - като например да направим така, че иконата на разширението да променя цвета си в зависимост от данните за въглерода. Това ми напомня как НАСА трябваше да оптимизира всяка система на космическия кораб Аполо. Те не можеха да си позволят никакви загуби на цикли или памет, защото животът зависеше от производителността. Макар че нашето браузър разширение не е толкова критично, същите принципи важат - ефективният код създава по-добро потребителско изживяване.
В предишните ни уроци изградихте форма, свързахте я с API и се справихте с асинхронно извличане на данни. Вашето разширение се оформя чудесно.
Сега трябва да добавим финалните щрихи - като например да направим иконата на разширението да променя цветовете си въз основа на въглеродните данни. Това ми напомня за начина, по който НАСА трябваше да оптимизира всяка система на космическия апарат Аполо. Те не можеха да си позволят никакви загубени цикли или памет, защото животи зависеха от производителността. Макар нашето браузърно разширение да не е чак толкова критично, същите принципи важат - ефективният код създава по-добри потребителски преживявания.
```mermaid
mindmap
root((Изпълнение и задачи на заден план))
Browser Performance
Rendering Pipeline
Asset Optimization
DOM Manipulation
JavaScript Execution
Profiling Tools
Developer Tools
Performance Tab
Timeline Analysis
Bottleneck Detection
Extension Architecture
Background Scripts
Content Scripts
Message Passing
Icon Management
Optimization Strategies
Code Splitting
Lazy Loading
Caching
Resource Compression
Visual Feedback
Dynamic Icons
Color Coding
Real-time Updates
User Experience
```
## Основи на уеб производителността
Когато кодът ви работи ефективно, хората могат действително *да усетят* разликата. Знаете онзи момент, когато страницата се зарежда мигновено или анимацията протича гладко? Това е добрата производителност в действие.
Производителността не е само въпрос на скорост - тя е за създаване на уеб изживявания, които се чувстват естествени, а не тромави и разочароващи. В ранните дни на компютърните технологии, Грейс Хопър известна с това, че държала наносекунда (парче жица около един фут дълго) на бюрото си, за да покаже колко далеч светлината пътува за една милиардна от секундата. Това било нейният начин да обясни защо всеки микросекунда има значение в компютърните технологии. Нека разгледаме инструментите за разследване, които ви помагат да разберете какво забавя нещата.
> "Производителността на уебсайта се отнася до две неща: колко бързо се зарежда страницата и колко бързо работи кодът на нея." -- [Zack Grossbart](https://www.smashingmagazine.com/2012/06/javascript-profiling-chrome-developer-tools/)
Темата за това как да направите вашите уебсайтове изключително бързи на всякакви устройства, за всякакви потребители, в всякакви ситуации, е очаквано обширна. Ето някои точки, които трябва да имате предвид, докато изграждате стандартен уеб проект или браузър разширение.
Първата стъпка в оптимизирането на вашия сайт е да разберете какво всъщност се случва зад кулисите. За щастие, вашият браузър разполага с мощни инструменти за разследване, вградени в него.
За да отворите Developer Tools в Edge, кликнете върху трите точки в горния десен ъгъл, след това отидете на More Tools > Developer Tools. Или използвайте клавишната комбинация: `Ctrl` + `Shift` + `I` на Windows или `Option` + `Command` + `I` на Mac. След като сте там, кликнете върху раздела Performance - това е мястото, където ще проведете вашето разследване.
Когато кодът ви работи ефективно, хората наистина могат да *усетят* разликата. Познавате онзи момент, когато страница се зарежда мигновено или анимация тече гладко? Това е добра производителност на работа.
Производителността не е само за скорост - а да създаваш уеб преживявания, които се чувстват естествени, а не тромави и разочароващи. В ранните дни на компютрите Грейс Хопър известно време държала наносекунда (парче проводник с дължина около една фут) на бюрото си, за да покаже колко далеч пътува светлината за една милиардна от секундата. Това бил нейният начин да обясни защо всеки микросекунд е важен в изчисленията. Нека разгледаме инструментите-детективи, които ще ви помогнат да разберете какво забавя нещата.
> "Производителността на уебсайта зависи от две неща: колко бързо се зарежда страницата и колко бързо работи кодът върху нея." -- [Зак Гросбарт](https://www.smashingmagazine.com/2012/06/javascript-profiling-chrome-developer-tools/)
Темата как да направите уебсайтовете си бързи на всякакви устройства, за всякакви потребители и във всякакви ситуации, разбира сее много обширна. Ето някои точки, които да имате предвид, докато изграждате стандартен уеб проект или браузърно разширение.
Първата стъпка в оптимизацията на сайта ви е да разберете какво всъщност се случва "под капака". За щастие, браузърът ви идва с мощни инструменти-детективи, вградени директно в него.
```mermaid
flowchart LR
A[HTML] --> B[Разбор]
B --> C[DOM Дърво]
D[CSS] --> E[Разбор]
E --> F[CSSOM]
G[JavaScript] --> H[Изпълнение]
C --> I[Дърво за рендиране]
F --> I
H --> I
I --> J[Оформление]
J --> K[Рисуване]
K --> L[Композиция]
L --> M[Показване]
subgraph "Критичен път на рендиране"
N["1. Разбор на HTML"]
O["2. Разбор на CSS"]
P["3. Изпълнение на JS"]
Q["4. Създаване на дърво за рендиране"]
R["5. Оформяне на елементи"]
S["6. Рисуване на пиксели"]
T["7. Композиране на слоеве"]
end
style M fill:#e8f5e8
style I fill:#fff3e0
style H fill:#ffebee
```
За да отворите Developer Tools в Edge, кликнете върху трите точки горе вдясно, след това отидете на More Tools > Developer Tools. Или използвайте клавишната комбинация: `Ctrl` + `Shift` + `I` в Windows или `Option` + `Command` + `I` в Mac. След като сте там, кликнете на таб Performance - тук ще правите вашето разследване.
**Ето вашия инструментариум за разследване на производителността:**
- **Отворете** Developer Tools (ще ги използвате постоянно като разработчик!)
- **Отидете** на раздела Performance - мислете за него като за фитнес тракер на вашето уеб приложение
**Ето вашия комплект за разследване на производителността:**
- **Отворете** Developer Tools (ще ги използвате постоянно като разработчици!)
- **Отидете** в таб Performance - помислете за него като фитнес тракер за вашето уеб приложение
- **Натиснете** бутона Record и наблюдавайте страницата в действие
- **Изучете** резултатите, за да откриете какво забавя нещата
Нека опитаме това. Отворете уебсайт (Microsoft.com работи добре за тази цел) и кликнете върху бутона 'Record'. Сега обновете страницата и наблюдавайте как профайлърът улавя всичко, което се случва. Когато спрете записа, ще видите подробен анализ на това как браузърът 'скриптира', 'рендва' и 'рисува' сайта. Това ми напомня как контролният център следи всяка система по време на изстрелване на ракета - получавате данни в реално време за точно какво се случва и кога.
✅ [Документацията на Microsoft](https://docs.microsoft.com/microsoft-edge/devtools-guide/performance/?WT.mc_id=academic-77807-sagibbon) има много повече подробности, ако искате да се задълбочите.
> Съвет: Изчистете кеша на браузъра си преди тестване, за да видите как вашият сайт се представя за първоначални посетители - обикновено е доста различно от повторните посещения!
Изберете елементи от времевата линия на профила, за да увеличите събитията, които се случват, докато страницата ви се зарежда.
Вземете моментна снимка на производителността на страницата си, като изберете част от времевата линия на профила и погледнете панела за обобщение:
✅ Запознайте сес вашия профайлър! Отворете инструментите за разработчици на този сайт и вижте дали има някакви затруднения. Кой е най-бавно зареждащият сересурс? Най-бързият?
## Какво да търсите при профайлиране
Нека опитаме. Отворете уебсайт (Microsoft.com е добър пример) и кликнете бутона 'Record'. Сега обновете страницата и гледайте профайлъра как улавя всичко, което се случва. Когато спрете записа, ще видите детайлно разграфяване на това как браузърът „изпълнява скриптове“, „рендерира“ и „рисува“ сайта. Това ми напомня за начина, по който мисия контрол следи всяка система по време на изстрелване на ракета - получавате данни в реално време за точно какво и кога се случва.
✅ Документацията на [Microsoft](https://docs.microsoft.com/microsoft-edge/devtools-guide/performance/?WT.mc_id=academic-77807-sagibbon) има много повече подробности, ако искате да навлезете по-дълбоко
> Професионален съвет: Изчистете кеша на браузъра си преди теста, за да видите как се представя сайтът за първи път посетителите - обикновено е доста различно от повторните посещения!
Изберете части от хронологията на профила, за да приближите събития, които се случват докато страницата се зарежда.
Вземете моментна снимка на производителността на страницата, като изберете част от хронологията на профила и погледнете обобщения прозорец:
Проверете прозореца с журнал на събития, за да видите дали някое събитие е продължило повече от 15 ms:

✅ Запознайте сес профайлъра! Отворете developer tools на този сайт и вижте дали има тесни места. Кой е най-бавно зареждащият сересурс? Най-бързият?
```mermaid
flowchart TD
A[Отвори DevTools] --> B[Отиди в раздел Производителност]
B --> C[Кликни бутон Запис]
C --> D[Изпълни действия]
D --> E[Спиране на записа]
E --> F{Анализиране на резултатите}
F --> G[Провери хронологията]
F --> H[Преглед на мрежата]
F --> I[Изследване на скриптове]
F --> J[Идентифицирай събития за рисуване]
G --> K{Дълги задачи?}
H --> L{Големи ресурси?}
I --> M{Блокиране на рендериране?}
J --> N{Скъпи рисувания?}
K -->|Да| O[Оптимизирай JavaScript]
L -->|Да| P[Компресирай ресурси]
M -->|Да| Q[Добави Async/Defer]
N -->|Да| R[Оптимизирай стилове]
O --> S[Тествай отново]
P --> S
Q --> S
R --> S
style A fill:#e1f5fe
style F fill:#fff3e0
style S fill:#e8f5e8
```
## Какво да търсим при профилиране
Изпълнението на профайлъра е само началото - истинското умение е да разберете какво всъщност ви казват тези цветни графики. Несе притеснявайте, ще се научите да ги разчитате. Опитните разработчици сасе научили да разпознават предупредителните знаци, преди да се превърнат в сериозни проблеми.
Стартирането на профайлъра е само началото - истинското умение е да разбирате какво всъщност ви казват тези цветни графики. Несе притеснявайте, ще свикнете с четенето им. Опитните разработчици са научили да откриват предупредителните знаци, преди те да се превърнат в големи проблеми.
Нека поговорим за обичайните заподозрени - проблемите с производителността, които често се промъкват в уеб проектите. Както Мария Кюри трябваше внимателно да следи нивата на радиация в лабораторията си, така и ние трябва да следим за определени модели, които показват, че се задават проблеми. Ранното им откриване ще ви спести (и на вашите потребители) много разочарование.
Нека поговорим за типичните заподозрени - нарушителите на производителността, които обикновено се промъкват в уеб проектите. Както Мария Кюри внимателно наблюдавала нивата на радиация в лабораторията си, така и ние трябва да следим за определени модели, които показват разрастващи се проблеми. Ако ги хванете рано, ще спестите много фрустрация на себе си и на потребителите.
**Размери на ресурсите**: Уебсайтовете стават все "по-тежки" през годините, и голяма част от този допълнителен товар идва от изображенията. Това е като да пълним все повече и повече в нашите дигитални куфари.
**Размер на ресурсите**: Уебсайтовете стават „по-тежки“ с времето, и голяма част от този допълнителен товар идва от изображения. Все едно, че пълним повече и повече дигитални куфари.
✅ Разгледайте [Internet Archive](https://httparchive.org/reports/page-weight), за да видите как размерите на страниците сасе увеличили с времето - това е доста показателно.
✅ Вижте [Internet Archive](https://httparchive.org/reports/page-weight), за да видите как размерите на страниците сасе увеличили с времето - доста показателно.
**Ето как да поддържате оптимизирани ресурсите си:**
- **Компресирайте** изображенията! Съвременни формати като WebP могат значително да намалят размера на файловете
- **Сервирайте** правилния размер на изображението за всяко устройство - няма нужда да изпращате огромни изображения за десктоп на телефони
- **Минимизирайте** вашия CSS и JavaScript - всеки байт има значение
- **Използвайте** lazy loading, за да се изтеглят изображенията само когато потребителите действително превъртат до тях
**Как да поддържате ресурсите си оптимизирани:**
- **Компресирайте** изображенията! Модерни формати като WebP могат значително да намалят размера на файловете
- **Сервирайте** правилния размер изображение за всяко устройство - няма нужда огромни десктоп изображения да се изпращат на телефони
- **Минимизирайте** CSS и JavaScript - всеки байт има значение
- **Използвайте** lazy loading, така че изображенията да се свалят само когато потребителят ги достигне с превъртане
**Обхождане на DOM**: Браузърът трябва да изгради своя Document Object Model въз основа на кода, който пишете, така че в интерес на добрата производителност на страницата е да поддържате таговете си минимални, като използвате и стилизирате само това, което е необходимо за страницата. Например, излишният CSS, свързан със страницата, може да бъде оптимизиран; стиловете, които трябва да се използват само на една страница, не трябва да бъдат включени в основния стилов файл.
**Обхождане на DOM**: Браузърът трябва да изгради своя Document Object Model въз основа на кода, който пишете, затова е в интерес на добрата производителност да запазите минимално използването на тагове, като прилагате стилизиране само за нужното малко. Към тази тема може да се оптимизира излишния CSS; стилове, използвани само за една страница, не е нужно да са в главния стилов файл, например.
**Основни стратегии за оптимизация на DOM:**
- **Минимизирайте** броя на HTML елементите и нивата на вложеност
- **Премахнете** неизползваните CSS правила и ефективно консолидирайте стиловите файлове
- **Организирайте** CSS така, че да зарежда само необходимото за всяка страница
- **Структурирайте** HTML семантично за по-добро парсиране от браузъра
**JavaScript**: Всеки разработчик на JavaScript трябва да следи за скриптове, които блокират рендирането и трябва да бъдат заредени преди останалата част от DOM да може да бъде обходена и нарисувана в браузъра. Помислете за използването на `defer`с вашите inline скриптове (както е направено в модула Terrarium).
**Съвременни техники за оптимизация на JavaScript:**
- **Използвайте** атрибута `defer`, за да зареждате скриптове след парсиране на DOM
- **Прилагайте** разделяне на код, за да зареждате само необходимия JavaScript
- **Използвайте** lazy loading за некритична функционалност
- **Минимизирайте** използването на тежки библиотеки и рамки, когато е възможно
✅ Опитайте някои сайтове на [Site Speed Test website](https://www.webpagetest.org/), за да научите повече за общите проверки, които се правят за определяне на производителността на сайта.
Сега, когато имате представа как браузърът рендира ресурсите, които му изпращате, нека разгледаме последните няколко неща, които трябва да направите, за да завършите вашето разширение:
### Създайте функция за изчисляване на цвят
Сега ще създадем функция, която превръща числовите данни в значими цветове. Мислете за това като за система със светофар - зелено за чиста енергия, червено за висока въглеродна интензивност.
Тази функция ще вземе данните за CO2 от нашия API и ще определи кой цвят най-добре представя въздействието върху околната среда. Това е подобно на начина, по който учените използват цветово кодиране в топлинни карти, за да визуализират сложни модели на данни - от температурите на океаните до формирането на звезди. Нека добавим това в `/src/index.js`, точно след тези `const` променливи, които настроихме по-рано:
- **Минимизира** броя на HTML елементите и нивата на вложеност
- **Премахва** неизползваните CSS правила и консолидира стиловете ефективно
- **Организира** CSS така, че да се зарежда само необходимото за всяка страница
- **Структурира** HTML семантично за по-добро парсиране от браузъра
**JavaScript**: Всеки JavaScript разработчик трябва да наблюдава за 'render-blocking' скриптове, които трябва да се заредят преди останалата част от DOM да може да се обходи и нарисува в браузъра. Помислете да използвате `defer` при вашите inline скриптове (както е направено в Terrarium модула).
**Модерни техники за оптимизация на JavaScript:**
- **Използва** атрибута `defer` за зареждане на скриптове след парсиране на DOM
- **Прилага** разделяне на код (code splitting), за да зарежда само необходимия JavaScript
- **Използва** lazy loading за некритична функционалност
- **Минимизира** използването на тежки библиотеки и фреймворци когато е възможно
✅ Изпробвайте някои сайтове в [Site Speed Test сайт](https://www.webpagetest.org/), за да научите повече за често правените проверки за определяне на производителността.
### 🔄 **Педагогическа проверка**
**Разбиране на производителността**: Преди да започнете с функциите на разширението, уверете се, че можете:
- ✅ Да обясните критичния път на рендериране от HTML до пикселите
- ✅ Да идентифицирате често срещани задържания на производителността в уеб приложения
- ✅ Да използвате инструменти за разработчици в браузъра за профилиране на производителността на страницата
- ✅ Да разбирате как размерът на ресурсите и сложността на DOM влияят на скоростта
**Бърз тест**: Какво се случва, когато имате render-blocking JavaScript?
*Отговор: Браузърът трябва да изтегли и изпълни скрипта, преди да може да продължи с парсирането на HTML и рендерирането на страницата*
**Реално въздействие върху производителността:**
- **100 ms забавяне**: Потребителите усещат забавянето
- **1 секунда забавяне**: Потребителите започват да губят фокус
- **3+ секунди**: 40% от потребителите изоставят страницата
- **Мобилни мрежи**: Производителността има още по-голямо значение
Сега, когато имате представа как браузърът рендерира ресурсите, които му изпращате, нека разгледаме последните няколко неща, които трябва да направите, за да завършите разширението си:
### Създайте функция за изчисляване на цветове
Сега ще създадем функция, която превръща числови данни в смислени цветове. Помислете за това като за система със светофар - зелено за чиста енергия, червено за висока въглеродна интензивност.
Тази функция ще вземе CO2 данните от нашето API и ще определи кой цвят най-добре отразява екологичното въздействие. Това е подобно на начина, по който учените използват цветово кодиране в топлинни карти за визуализация на сложни модели на данни - от температурите на океаните до формирането на звезди. Нека добавим това в `/src/index.js`, точно след онези `const` променливи, които зададохме по-рано:
```mermaid
flowchart LR
A[Стойност CO2] --> B[Намиране на най-близката скала]
B --> C[Вземи индекс на скалата]
C --> D[Прекарване на цвят]
D --> E[Изпрати към фона]
subgraph "Цветова скала"
F["0-150: Зелен (Чист)"]
G["150-600: Жълт (Умерен)"]
H["600-750: Оранжев (Висок)"]
I["750+: Кафяв (Много висок)"]
end
subgraph "Прехвърляне на съобщения"
J[Скрипт за съдържание]
K[chrome.runtime.sendMessage]
L[Фонов скрипт]
M[Актуализация на иконата]
end
style A fill:#e1f5fe
style D fill:#e8f5e8
style E fill:#fff3e0
```
```javascript
function calculateColor(value) {
// Define CO2 intensity scale (grams per kWh)
// Дефинирайте скала за интензитет на CO2 (грама на kWh)
const co2Scale = [0, 150, 600, 750, 800];
// Corresponding colors from green (clean) to dark brown (high carbon)
// Съответстващи цветове от зелено (чисто) до тъмнокафяво (високо съдържание на въглерод)
- **Настройва** два масива - един за нивата на CO2, друг за цветовете (зелено = чисто, кафяво = мръсно!)
- **Намира** най-близкото съответствие на нашата реална стойност на CO2, използвайки интересен метод за сортиране на масиви
- **Взема** съответстващия цвят, използвайки метода findIndex()
- **Изпраща** съобщение до фоновия скрипт на Chrome с избрания от нас цвят
- **Използва** шаблонни литерали (тези обратни кавички) за по-чисто форматиране на стрингове
- **Организира** всичко с декларации const
API-то `chrome.runtime` [API](https://developer.chrome.com/extensions/runtime) е като нервната система на вашето разширение - то управлява цялата комуникация и задачи зад кулисите:
> "Използвайте API-то chrome.runtime, за да извлечете фоновата страница, да върнете подробности за манифеста и да слушате и отговаряте на събития в жизнения цикъл на приложението или разширението. Можете също така да използвате този API, за да конвертирате относителния път на URL адресите в напълно квалифицирани URL адреси."
**Защо API-то Chrome Runtime е толкова полезно:**
- **Позволява** различните части на вашето разширение да комуникират помежду си
- **Управлява** фоновата работа без да блокира потребителския интерфейс
- **Контролира** събитията от жизнения цикъл на вашето разширение
- **Улеснява** предаването на съобщения между скриптовете
✅ Ако разработвате това браузър разширение за Edge, може да ви изненада, че използвате API на Chrome. Новите версии на браузъра Edge работят на браузърния двигател Chromium, така че можете да се възползвате от тези инструменти.
> **Съвет**: Ако искате да профайлирате браузър разширение, стартирайте инструментите за разработчици от самото разширение, тъй като то е отделен браузърен инстанс. Това ви дава достъп до специфични за разширението метрики за производителност.
- **Настройва** два масива - един за нивата на CO2, друг за цветове (зелено = чисто, кафяво = замърсено!)
- **Намира** най-близкото съвпадение с нашата реална стойност на CO2 чрез подредба на масив
- **Взима** съответния цвят чрез метода findIndex()
- **Изпраща** съобщение към фоновия скрипт на Chrome с избрания цвят
- **Използва** шаблонни низове (тези обратни кавички) за по-чисто форматиране на текст
- **Поддържа** всичко организирано с const декларирания
API-то на `chrome.runtime`е като нервната система на вашето разширение - то управлява цялата комуникация и задачи зад кулисите:
> "Използвайте chrome.runtime API за достъп до страницата на фона, връщане на детайли за манифеста и слушане и отговор на събития в жизнения цикъл на приложението или разширението. Можете също да използвате това API за конвертиране на относителни пътища на URL адреси в пълни URL адреси."
**Защо Chrome Runtime API е толкова удобен:**
- **Позволява** различните части на разширението да си говорят
- **Обработва** фоновата работа без да блокира потребителския интерфейс
- **Управлява** събитията от жизнения цикъл на разширението
- **Прави** предаването на съобщения между скриптове много лесно
✅ Ако разработвате това браузърно разширение за Edge, може да ви изненада, че използвате chrome API. По-новите версии на Edge ползват Chromium браузърното ядро, затова можете да използвате тези инструменти.
```mermaid
architecture-beta
group browser(logos:chrome)[Браузър]
service popup(logos:html5)[Изскачащ интерфейс] in browser
service content(logos:javascript)[Скрипт за съдържание] in browser
service background(database)[Фонов скрипт] in browser
service api(logos:api)[Външен API] in browser
popup:R -- L:content
content:R -- L:background
background:T -- B:api
content:T -- B:api
junction junctionCenter in browser
popup:R -- L:junctionCenter
junctionCenter:R -- L:background
```
> **Професионален съвет**: Ако искате да профилирате браузърно разширение, стартирайте developer tools от самото разширение, тъй като то е отделен браузър енстанс. Това ви дава достъп до специфични за разширението метрики за производителност.
### Задайте цвят по подразбиране за иконата
### Задайте подразбиращ се цвят на иконата
Преди да започнем да извличаме реални данни, нека дадем на нашето разширение начална точка. Никой не обича да гледа празна или счупена икона. Ще започнем със зелен цвят, за да знаят потребителите, че разширението работи от момента на инсталирането му.
Преди да започнем да изтегляме реални данни, нека дадем на разширението начална точка. Никой не обича да гледа празна или "счупена" икона. Ще започнем със зелен цвят, за да знаят потребителите, че разширението работи от момента на инсталиране.
Във вашата функция `init()`, нека настроим тази зелена икона по подразбиране:
Във функцията`init()` нека настроим тази подразбираща сезелена икона:
- **Задава** неутрален зелен цвят като състояние по подразбиране
- **Осигурява** незабавна визуална обратна връзка, когато разширениетосе зарежда
- **Установява** модела на комуникация с фоновия скрипт
- **Гарантира**, че потребителите виждат функционално разширение преди зареждането на данни
- **Настройва** неутрален зелен цвят като подразбиращо се състояние
- **Осигурява** незабавна визуална обратна връзка, когато се зарежда разширението
- **Установява** образец на комуникация с фоновия скрипт
- **Гарантира** че потребителите виждат работещо разширение преди данните да се заредят
### Извикайте функцията, изпълнете извикването
### Извикайте функцията, изпълнете повикването
Сега нека свържем всичко заедно, така че когато пристигнат нови данни за CO2, вашата икона автоматично да се актуализира с правилния цвят. Това е като свързване на последния кръг в електронно устройство - изведнъж всички отделни компоненти работят като една система.
Сега нека свържим всичко така, че когато получим нови CO2 данни, иконата ви автоматично да се обновява с правилния цвят. Това е като свързване на последната верига в електронно устройство - изведнъж всички компоненти работят като една система.
Добавете този ред точно след като получите данните за CO2 от API-то:
Добавете този ред веднага след като получите CO2 данните от API-то:
```javascript
// After retrieving CO2 data from the API
// let CO2 = data.data[0].intensity.actual;
// След извличане на данни за CO2 от API-то
// нека CO2 = data.data[0].intensity.actual;
calculateColor(CO2);
```
**Тази интеграция постига:**
- **Свързва** потока от данни на API с визуалната индикаторна система
- **Задейства** автоматични актуализации на иконите, когато пристигнат нови данни
- **Осигурява** визуална обратна връзка в реално време въз основа на текущата въглеродна интензивност
- **Поддържа** разделението на отговорностите между извличането на данни и логиката на дисплея
- **Свързва** потока от API данни с визуалната индикация
- **Задейства** обновявания на иконата автоматично при пристигане на нови данни
- **Гарантира** визуална обратна връзка в реално време въз основа на текущата въглеродна интензивност
- **Поддържа** разделението между логиката за извличане на данни и показване
И накрая, в `/dist/background.js`, добавете слушател за тези фонови действия:
И накрая, в `/dist/background.js` добавете слушателя за тези повиквания към фоновата задача:
```javascript
// Listen for messages from the content script
// Слушайте за съобщения от скрипта на съдържанието
// Borrowed from energy lollipop extension - nice feature!
// Рисувайте динамичен икон с помощта на Canvas API
// Взето назаем от разширението energy lollipop - хубава функция!
function drawIcon(value) {
// Create an offscreen canvas for better performance
// Създайте офскрийн платно за по-добра производителност
const canvas = new OffscreenCanvas(200, 200);
const context = canvas.getContext('2d');
// Draw a colored circle representing carbon intensity
// Нарисувайте цветен кръг, представляващ интензивността на въглерода
context.beginPath();
context.fillStyle = value.color;
context.arc(100, 100, 50, 0, 2 * Math.PI);
context.fill();
// Return the image data for the browser icon
// Върнете данните на изображението за иконата на браузъра
return context.getImageData(50, 50, 100, 100);
}
```
**Ето какво прави този фонов скрипт:**
- **Слуша** за съобщения от вашия основен скрипт (като рецепционист, който приема обаждания)
- **Обработва** тези заявки 'updateIcon', за да промени иконата на вашата лента с инструменти
- **Създава** нови икони в движение
Ето една интересна детективска мисия: изберете няколко уебсайта с отворен код, които съществуват от години (като Wikipedia, GitHub или Stack Overflow) и разгледайте тяхната история на комитите. Можете ли да откриете къде са направили подобрения в производителността? Какви проблеми сасе появявали многократно?
- **Слуша** за съобщения от основния ви скрипт (като рецепционист, който приема обаждания)
- **Обработва** заявките 'updateIcon' за промяна на вашата икона на лентата с инструменти
- **Създава** нови икони в движение, използвайки Canvas API
- **Рисува** прост цветен кръг, който показва текущата въглеродна интензивност
- **Обновява** лентата с инструменти на браузъра с новата икона
- **Използва** OffscreenCanvas за гладка производителност (без блокиране на UI)
✅ Ще научите повече за Canvas API в уроците за [Space Game](../../6-space-game/2-drawing-to-canvas/README.md).
Browser->>Browser: Актуализира иконата на лентата с инструменти
```
### 🔄 **Педагогическа проверка**
**Пълно разбиране на разширението**: Уверете се, че владеете цялата система:
- ✅ Как работи предаването на съобщения между различни скриптове на разширението?
- ✅ Защо използваме OffscreenCanvas вместо обикновения Canvas за производителност?
- ✅ Каква роля играе Chrome Runtime API в архитектурата на разширението?
- ✅ Как алгоритъмът за изчисляване на цветовете свързва данните с визуалната обратна връзка?
**Съображения за производителността**: Вашето разширение сега демонстрира:
- **Ефективно съобщаване**: Чиста комуникация между скриптовите контексти
- **Оптимизирано изобразяване**: OffscreenCanvas предотвратява блокирането на интерфейса
- **Актуализации в реално време**: Динамична промяна на иконата въз основа на живи данни
- **Управление на паметта**: Подходящо почистване и обработка на ресурсите
**Време е да тествате вашето разширение:**
- **Постройте** всичко с`npm run build`
- **Презаредете** разширението в браузъра (не забравяйте този важен етап)
- **Отворете** разширението и наблюдавайте как иконата променя цветовете си
- **Проверете** как реагира на реални данни за въглерод от целия свят
Сега ще разберете мигновено дали е подходящо време за това пране или трябва да изчакате по-чиста енергия. Току-що създадохте нещо наистина полезно и научихте за производителността на браузъра по пътя.
## GitHub Copilot Agent Предизвикателство 🚀
Използвайте Agent режима, за да изпълните следното предизвикателство:
**Описание:** Подобрете възможностите за следене на производителността на браузърното разширение, като добавите функция, която следи и показва времето за зареждане на различните компоненти на разширението.
**Задание:** Създайте система за мониторинг на производителността на разширението, която измерва и записва времето за зареждане на CO2 данни от API, изчисляване на цветовете и актуализиране на иконата. Добавете функция, наречена `performanceTracker`, която използва Performance API за измерване на тези операции и показва резултатите в конзолата на браузъра с времеви отметки и метрики за продължителност.
Научете повече за [agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
## 🚀 Предизвикателство
Ето интересна детективска задача: изберете няколко популярни уебсайта с отворен код, които съществуват от години (например Wikipedia, GitHub или Stack Overflow) и разгледайте историята на техните комити. Можете ли да откриете къде са направени подобрения на производителността? Какви проблеми се появяват отново и отново?
**Вашият подход за разследване:**
- **Търсете** в съобщенията на комитите думи като "оптимизиране", "производителност" или "по-бързо"
- **Наблюдавайте** за модели - дали постоянно поправят едни и същи типове проблеми?
- **Идентифицирайте** общите причини за забавяне на уебсайтовете
- **Споделете** какво сте открили - други разработчици могат да се учат от примери от реалния свят
- **Търсете** в съобщенията на комитите думи като „optimize“, „performance“ или „faster“
- **Наблюдавайте** модели – поправят ли едни и същи типове проблеми
- **Идентифицирайте** често срещаните причини за забавяне на уебсайтовете
- **Споделете** откритията си – други разработчици могат да се учат от реални примери
## Тест след лекцията
[Тест след лекцията](https://ff-quizzes.netlify.app/web/quiz/28)
## Преглед и самостоятелно обучение
Помислете дали да се абонирате за [бюлетин за производителност](https://perf.email/)
Разгледайте някои от начините, по които браузърите измерват уеб производителността, като прегледате разделите за производителност в техните инструменти за разработчици. Откривате ли някакви съществени разлики?
## Преглед и Самообучение
Помислете да се абонирате за [бюлетин за производителност](https://perf.email/)
Разгледайте някои от начините, по които браузърите оценяват уеб производителността, като използвате табовете за производителност в уеб инструментите им. Сблъсквате ли сес големи разлики?
### ⚡ **Какво можете да направите в следващите 5 минути**
- [ ] Отворете Task Manager на браузъра (Shift+Esc в Chrome), за да видите използването на ресурси от разширенията
- [ ] Използвайте таба Performance в DevTools, за да запишете и анализирате производителността на страницата
- [ ] Проверете страницата Extensions на браузъра, за да видите кои разширения влияят на времето за стартиране
- [ ] Опитайте временно да деактивирате разширения, за да видите разликата в производителността
### 🎯 **Какво можете да постигнете този час**
- [ ] Попълнете теста след урока и разберете концепциите за производителност
- [ ] Имплементирайте background скрипт за вашето браузърно разширение
- [ ] Научете как да използвате browser.alarms за ефективни задачи в бекграунд
- [ ] Практикувайте съобщения между content скриптове и background скриптове
- [ ] Измерете и оптимизирайте използването на ресурси на вашето разширение
### 📅 **Вашето пътуване към оптимизация през седмицата**
- [ ] Създайте високопроизводително браузърно разширение с бекграунд функционалност
- [ ] Усвоете service workers и модерната архитектура на разширения
- [ ] Имплементирайте ефективна синхронизация на данни и кеширане
- [ ] Научете напреднали техники за дебъг на производителността на разширения
- [ ] Оптимизирайте разширението и за функционалност, и за използване на ресурси
- [ ] Създайте комплексни тестове за различни сценарии на производителност
### 🌟 **Вашето месечно майсторство в оптимизацията**
- [ ] Създавайте разширения за браузъри на ниво предприятие с оптимална производителност
- [ ] Научете за Web Workers, Service Workers и съвременната уеб производителност
- [ ] Приносете в проекти с отворен код, фокусирани върху оптимизацията на производителността
- [ ] Усвоете вътрешната архитектура на браузърите и напреднали дебъг техники
- [ ] Създавайте инструменти за мониторинг на производителността и ги документирайте
- [ ] Станете експерт по производителност, който помага да се оптимизират уеб приложения
## 🎯 Вашият график за овладяване на браузърните разширения
```mermaid
timeline
title Пълна прогресия на разработката на разширение
section Основи на представянето (20 минути)
Профилиране на браузъра: Майсторство с DevTools
: Анализ на времевата линия
: Идентифициране на тесни места
: Критичен път за рендиране
section Фонови задачи (25 минути)
Архитектура на разширението: Препращане на съобщения
: Фонови скриптове
: Използване на Runtime API
: Комуникация между контексти
section Визуална обратна връзка (30 минути)
Динамичен UI: Алгоритми за изчисляване на цветове
: Интеграция на Canvas API
: Генериране на икони
: Актуализации в реално време
section Оптимизация на представянето (35 минути)
Ефективен код: Асинхронни операции
: Управление на паметта
: Очистване на ресурси
: Мониторинг на представянето
section Готов за продукция (45 минути)
Полиране и тестване: Съвместимост между браузъри
: Обработка на грешки
: Потребителско изживяване
: Валидиране на представянето
section Разширени функции (1 седмица)
Екосистема на разширението: Chrome Web Store
: Обратна връзка от потребители
: Интеграция на аналитика
: Управление на актуализации
section Професионално развитие (2 седмици)
Предприятия разширения: Сътрудничество в екип
: Прегледи на кода
: CI/CD потоци
: Аудити за сигурност
section Експертно майсторство (1 месец)
Експертиза в платформата: Разширени Chrome APIs
: Оптимизация на представянето
: Архитектурни шаблони
: Принос към отворен код
```
### 🛠️ Вашият пълен комплект за разработване на разширения
След като завършихте тази трилогия, вие вече сте овладели:
- **Архитектура на браузъра**: Дълбоко разбиране как разширенията се интегрират с браузърните системи
- **Профилиране на производителността**: Умения за идентифициране и коригиране на „врати на бутилка“ с помощта на инструменти за разработчици
- **Асинхронно програмиране**: Модерни JavaScript модели за отзивчиви, неблокиращи операции
- **Интеграция с API**: Извличане на външни данни с автентикация и обработка на грешки
- **Визуален дизайн**: Динамични актуализации на потребителския интерфейс и графики базирани на Canvas
- **Препращане на съобщения**: Комуникация между скриптове в архитектура на разширения
- **Потребителски опит**: Показване на състояния на зареждане, управление на грешки и интуитивни взаимодействия
- **Производствени умения**: Тестване, дебъг и оптимизация за реално приложение
**Приложения в реалния свят**: Вашите умения за разработка на разширения се прилагат директно в:
- **Прогресивни уеб приложения**: Подобна архитектура и модели на производителност
- **Electron настолни приложения**: Кросплатформени приложения суеб технологии
- **Мобилни хибридни приложения**: Разработка с Cordova/PhoneGap, използвайки уеб API
- **Предприятия уеб приложения**: Комплексни табла и инструменти за продуктивност
- **Разширения за Chrome DevTools**: Разширена разработка и дебъг инструменти
- **Интеграция суеб API**: Всяко приложение, което използва външни услуги
**Професионално въздействие**: Вече можете:
- **Да създавате** разширения за браузъри, готови за продукция, от концепция до внедряване
- **Да оптимизирате** уеб приложение по отношение на производителността с индустриални инструменти за профилиране
- **Да архитектурирате** мащабируеми системи с правилно разделение на отговорностите
- **Да дебъгвате** сложни асинхронни операции и комуникация между контексти
- **Да допринасяте** за проекти с отворен код и стандарти на браузърите
**Възможности за следващото ниво**:
- **Разработчик за Chrome Web Store**: Публикувайте разширения за милиони потребители
- **Инженер по уеб производителността**: Специализирайте в оптимизация и потребителски опит
- **Разработчик на браузърни платформи**: Допринасяйте за развитието на браузърните ядра
- **Създател на рамки за разширения**: Създавайте инструменти, които помагат на други разработчици
- **Отношения с разработчици**: Споделяйте знания чрез обучение и създаване на съдържание
🌟 **Постижение отключено**: Създадохте пълноценно, функционално браузърно разширение, което демонстрира професионални практики и съвременни уеб стандарти!
## Задача
@ -248,5 +591,7 @@ function drawIcon(value) {
---
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Отказ от отговорност**:
Този документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за каквито и да било недоразумения или погрешни интерпретации, произтичащи от използването на този превод.
Този документ е преведен с помощта на AI преводаческа услуга [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, имайте предвид, че автоматизираните преводи могат да съдържат грешки или неточности. Оригиналният документ на неговия език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човешки преводач. Ние не носим отговорност за недоразумения или неправилни тълкувания, произтичащи от използването на този превод.
Използвайки API на tmrow за CO2 Signal, създайте разширение за браузър, което да ви напомня директно в браузъра за натовареността на електрическата мрежа във вашия регион. Използването на това разширение ще ви помогне да вземате информирани решения за вашите дейности въз основа на тази информация.


## Първи стъпки
@ -31,7 +31,7 @@ npm run build
За да го инсталирате в Edge, използвайте менюто с „три точки“ в горния десен ъгъл на браузъра, за да намерите панела с разширения. Оттам изберете „Load Unpacked“, за да заредите ново разширение. Отворете папката „dist“ при подканата и разширението ще се зареди. За да го използвате, ще ви е необходим API ключ за CO2 Signal ([вземете го тук чрез имейл](https://www.co2signal.com/) - въведете вашия имейл в полето на тази страница) и [код за вашия регион](http://api.electricitymap.org/v3/zones), съответстващ на [Electricity Map](https://www.electricitymap.org/map) (например в Бостън използвам 'US-NEISO').
След като въведете API ключа и региона в интерфейса на разширението, цветната точка в лентата на разширението на браузъра трябва да се промени, за да отрази енергийната натовареност на вашия регион. Тя ще ви даде насоки за това кои дейности, изискващи повече енергия, са подходящи за изпълнение. Концепцията зад тази система с „точка“ ми беше вдъхновена от [разширението Energy Lollipop](https://energylollipop.com/) за емисиите в Калифорния.
Използвайки API-то на CO2 Signal от tmrow за проследяване на потреблението на електроенергия, създайте разширение за браузър, което да ви напомня директно в браузъра за потреблението на електроенергия във вашия регион. Използването на това разширение ще ви помогне да вземате информирани решения за вашите дейности въз основа на тази информация.


## Начало
@ -31,7 +31,7 @@ npm run build
За да го инсталирате на Edge, използвайте менюто с 'три точки' в горния десен ъгъл на браузъра, за да намерите панела за разширения. Оттам изберете 'Зареждане на разархивирано разширение', за да добавите ново разширение. Отворете папката 'dist', когато бъдете подканени, и разширението ще се зареди. За да го използвате, ще ви е необходим API ключ за CO2 Signal ([вземете го тук по имейл](https://www.co2signal.com/) - въведете вашия имейл в полето на тази страница) и [код за вашия регион](http://api.electricitymap.org/v3/zones), съответстващ на [Картата на електроенергията](https://www.electricitymap.org/map) (например за Бостън използвам 'US-NEISO').
След като въведете API ключа и региона в интерфейса на разширението, цветната точка в лентата на разширенията на браузъра трябва да се промени, за да отрази потреблението на енергия във вашия регион. Това ще ви даде индикатор за енергоемките дейности, които е подходящо да извършвате. Концепцията зад тази система с 'точки' ми беше вдъхновена от [разширението Energy Lollipop](https://energylollipop.com/) за емисиите в Калифорния.
Използване на API на CO2 Signal от tmrow за проследяване на потреблението на електроенергия, създаване на браузър разширение, което да ви напомня колко натоварено е потреблението на електроенергия във вашия регион. Използването на това разширение ще ви помогне да вземате решения за вашите дейности въз основа на тази информация.


## Започване
@ -31,7 +31,7 @@ npm run build
За да го инсталирате в Edge, използвайте менюто „три точки“ в горния десен ъгъл на браузъра, за да намерите панела за разширения. Оттам изберете „Load unpacked“, за да заредите ново разширение. В подканата отворете папката „dist“ и разширението ще бъде заредено. За да го използвате, ще ви е необходим API ключ за CO2 Signal ([получете го тук чрез имейл](https://www.co2signal.com/) – въведете вашия имейл в полето на страницата) и [код за вашия регион](http://api.electricitymap.org/v3/zones) от [Electricity Map](https://www.electricitymap.org/map) (например, за Бостън използвам „US-NEISO“).
След като въведете API ключа и региона в интерфейса на разширението, цветната точка в лентата на браузър разширението трябва да се промени, за да отразява потреблението на енергия във вашия регион и да ви даде индикатор за това кои енергоемки дейности са подходящи за изпълнение. Концепцията за тази система с „точка“ ми беше вдъхновена от [Energy Lollipop Extension](https://energylollipop.com/) за емисиите в Калифорния.
Ще използваме API-то Signal CO2 на tmrow, за да следим потреблението на електричество и да създадем разширение за браузър, което да ви напомня директно в браузъра колко интензивно е използването на електричество във вашия регион. Използването на това специално разширение ще ви помогне да оцените дейностите си въз основа на тази информация.


## Начало
@ -31,7 +31,7 @@ npm run build
За да го инсталирате в Edge, използвайте менюто с "три точки" в горния десен ъгъл на браузъра, за да намерите панела за разширения. Ако не е активиран, включете Режим за разработчици (в долния ляв ъгъл). Изберете "Зареди разархивирано", за да добавите ново разширение. Отворете папката "dist" в подканата и разширението ще бъде заредено. За да го използвате, ще ви е необходим API ключ за CO2 Signal API (можете да го [получите тук чрез имейл](https://www.co2signal.com/) - въведете своя имейл в полето на тази страница) и [код за вашия регион](http://api.electricitymap.org/v3/zones), съответстващ на [електрическата карта](https://www.electricitymap.org/map) (например за Бостън, "US-NEISO").
След като въведете API ключа и региона в интерфейса на разширението, цветната точка в лентата на разширението на браузъра трябва да се промени, за да отрази енергийното потребление на региона и да предостави насоки за това кои дейности с висока енергийна консумация са подходящи за изпълнение. Концепцията зад тази система с "точки" е вдъхновена от [разширението Energy Lollipop](https://energylollipop.com/) за емисиите в Калифорния.
Създайте разширение за браузър, което използва API на CO2 Signal от tmrow, за да следи потреблението на енергия във вашия регион и да го показва като напомняне директно в браузъра. Това разширение може да се използва, за да вземате информирани решения относно вашите дейности въз основа на тази информация.


## Въведение
@ -31,7 +31,7 @@ npm run build
За да го инсталирате в Edge, намерете панела „Разширения“ от менюто с „три точки“ в горния десен ъгъл на браузъра. Оттам изберете „Load Unpacked“ и заредете новото разширение. Когато бъдете подканени, отворете папката „dist“, за да заредите разширението. За да го използвате, ще ви е необходим API ключ за CO2 Signal ([вземете го тук чрез имейл](https://www.co2signal.com/) - въведете имейла си в полето на тази страница) и [код за вашия регион](http://api.electricitymap.org/v3/zones), съвместим с [Electricity Map](https://www.electricitymap.org/map) (например за Бостън използвайте 'US-NEISO').
След като въведете API ключа и региона в интерфейса на разширението, цветна точка, която се показва в лентата на разширенията на браузъра, ще се променя, за да отразява енергийното потребление във вашия регион. Това ще ви помогне да определите кои дейности, изискващи енергия, са подходящи в момента. Концепцията за тази „точкова“ система е вдъхновена от [Energy Lollipop extension](https://energylollipop.com/) за емисиите в Калифорния.
Използвайки API на CO2 Signal от tmrow за проследяване на електрическата консумация, създайте разширение за браузър, което да ви предупреждава за нивото на електрическа консумация във вашия регион. Използването на това разширение ще ви помогне да вземате информирани решения относно вашите дейности въз основа на тази информация.


## Започнете оттук
@ -31,7 +31,7 @@ npm run build
За да го инсталирате в Edge, използвайте менюто с „три точки“ в горния десен ъгъл на браузъра, за да намерите панела Разширения. Оттам изберете „Load Unpacked“, за да заредите новото разширение. Отворете папката 'dist', когато бъдете подканени, и разширението ще бъде заредено. За да го използвате, ще ви е необходим API ключ за CO2 Signal ([вземете го тук чрез имейл](https://www.co2signal.com/) - въведете имейла си в полето на страницата) и [код за вашия регион](http://api.electricitymap.org/v3/zones), който съответства на [Electricity Map](https://www.electricitymap.org/map) (например в Бостън използвам 'US-NEISO').
След като въведете API ключа и региона в интерфейса на разширението, цветната точка в лентата на разширението на браузъра ще се променя, за да отразява енергийната консумация във вашия регион и ще ви дава насоки за подходящи дейности. Концепцията зад системата с „точки“ беше вдъхновена от [разширението за браузър Energy Lollipop](https://energylollipop.com/) за емисиите в Калифорния.
Използвайки API на tmrow за CO2 Signal, можете да следите електрическата консумация и да създадете разширение за браузър, което да ви напомня директно в браузъра колко интензивно е използването на електроенергия във вашия регион. Използването на това разширение ще ви помогне да вземате информирани решения за вашите дейности въз основа на тази информация.


## Първи стъпки
@ -31,7 +31,7 @@ npm run build
За да го инсталирате в Edge, използвайте менюто с „три точки“ в горния десен ъгъл на браузъра, за да намерите панела с разширения. Оттам изберете „Load Unpacked“, за да заредите ново разширение. Отворете папката „dist“ при подканата и разширението ще се зареди. За да го използвате, ще ви е необходим API ключ за CO2 Signal ([вземете го тук чрез имейл](https://www.co2signal.com/) - въведете вашия имейл в полето на тази страница) и [код за вашия регион](http://api.electricitymap.org/v3/zones), съответстващ на [Electricity Map](https://www.electricitymap.org/map) (например, в Бостън използвам „US-NEISO“).
След като въведете API ключа и региона в интерфейса на разширението, цветната точка в лентата на разширението на браузъра трябва да се промени, за да отрази енергийната консумация във вашия регион. Тя ще ви даде насоки за това кои дейности, изискващи повече енергия, са подходящи за изпълнение. Концепцията зад тази система с „точка“ ми беше вдъхновена от [Energy Lollipop разширението](https://energylollipop.com/) за емисиите в Калифорния.

Точно както контролът на мисията на НАСА координира множество системи по време на космически полет, ние ще създадем космическа игра, която демонстрира как различни части на една програма могат да работят заедно безпроблемно. Докато създавате нещо, което наистина можете да играете, ще научите основни концепции за програмиране, които се прилагат към всеки софтуерен проект.
Ще разгледаме два основни подхода за организиране на код: наследяване и композиция. Това не са просто академични концепции – те са същите модели, които задвижват всичко, от видеоигри до банкови системи. Също така ще внедрим система за комуникация, наречена pub/sub, която работи като комуникационните мрежи, използвани в космическите кораби, позволявайки на различни компоненти да споделят информация без да създават зависимости.
До края на тази серия ще разберете как да изграждате приложения, които могат да се мащабират и развиват – независимо дали разработвате игри, уеб приложения или друг софтуер.
## Предварителен тест
```mermaid
journey
title Вашето Пътешествие в Разработката на Игри
section Основи
Научете архитектура на игрите: 3: Student
Разберете наследяване: 4: Student
Изследвайте композиция: 4: Student
section Комуникация
Създайте pub/sub система: 4: Student
Проектирайте поток на събития: 5: Student
Свържете компоненти: 5: Student
section Приложение
Създайте игрови обекти: 5: Student
Имплементирайте шаблони: 5: Student
Планирайте структурата на играта: 5: Student
```

Точно както контролният център на NASA координира няколко системи по време на изстрелване в космоса, ние ще създадем космическа игра, която демонстрира как различни части на една програма могат да работят безпроблемно заедно. Докато създавате нещо, което действително можете да играете, ще научите основни концепции на програмирането, които се прилагат към всеки софтуерен проект.
Ще разгледаме два фундаментални подхода за организиране на кода: наследяване и композиция. Те не са просто академични концепции – това са същите модели, които захранват всичко от видеоигри до банкови системи. Ще имплементираме и комуникационна система, наречена pub/sub, която работи като комуникационните мрежи, използвани в космически кораби, позволявайки на различни компоненти да споделят информация без да създават зависимости.
Към края на тази серия ще разберете как да изграждате приложения, които могат да се разрастват и развиват – независимо дали разработвате игри, уеб приложения или която и да е друга софтуерна система.
[Квиз преди лекцията](https://ff-quizzes.netlify.app/web/quiz/29)
## Наследяване и композиция в разработката на игри
## Наследяване и Композиция в разработката на игри
С увеличаването на сложността на проектите, организацията на кода става критична. Това, което започва като прост скрипт, може да стане трудно за поддръжка без подходяща структура – подобно на това как мисиите на Аполо изискват внимателна координация между хиляди компоненти.
Снарастването на сложността на проектите, организацията на кода става критична. Това, което започва като прост скрипт, може да стане трудно за поддръжка без подходяща структура –точно както мисии Аполо изискваха внимателна координация между хиляди компоненти.
Ще разгледаме два основни подхода за организиране на код: наследяване и композиция. Всеки от тях има своите предимства, а разбирането на двата подхода ще ви помогне да изберете правилния за различни ситуации. Ще демонстрираме тези концепции чрез нашата космическа игра, където герои, врагове, бонуси и други обекти трябва да взаимодействат ефективно.
Ще разгледаме два фундаментални подхода за организиране на кода: наследяване и композиция. Всеки има различни предимства и разбирането и на двата ви помага да изберете правилния подход за различни ситуации. Ще демонстрираме тези концепции чрез нашата космическа игра, където герои, врагове, power-ups и други обекти трябва да взаимодействат ефективно.
✅ Една от най-известните книги за програмиране е свързана с [дизайнерски модели](https://en.wikipedia.org/wiki/Design_Patterns).
✅ Една от най-известните книги за програмиране някога написани е свързана с [дизайнерски шаблони](https://en.wikipedia.org/wiki/Design_Patterns).
Във всяка игра има `игрови обекти`– интерактивните елементи, които населяват игровия свят. Героите, враговете, бонусите и визуалните ефекти са всички игрови обекти. Всеки от тях съществува на определени координати на екрана, използвайки стойности `x` и `y`, подобно на поставянето на точки върху координатна равнина.
Във всяка игра имате`игрови обекти`– интерактивните елементи, които населяват игровия ви свят. Герои, врагове, power-ups и визуални ефекти са всички игрови обекти. Всеки съществува на специфични екранни координати, използвайки стойности `x` и `y`, подобно на поставянето на точки върху координатна равнина.
Въпреки визуалните си различия, тези обекти често споделят основни поведения:
- **Те съществуват някъде** – Всеки обект има x и y координати, за да знае играта къде да го нарисува
- **Много от тях могат да се движат** – Героите тичат, враговете преследват, куршумите летят по екрана
- **Те имат живот** – Някои остават завинаги, други (като експлозиите) се появяват за кратко и изчезват
- **Те реагират на неща** – Когато нещата се сблъскват, бонусите се събират, здравните ленти се обновяват
- **Съществуват някъде** – Всеки обект има x и y координати, за да знае играта къде да гоизобрази
- **Мнозина могат да се движат** – Герои тичат, врагове гонят, куршуми летят по екрана
- **Имат жизнен цикъл** – Някои остават вечно, други (като експлозии) се появяват за кратко и изчезват
- **Реагират на неща** – Когато неща се сблъскват, power-ups се събират, житейските ленти се обновяват
✅ Помислете за игра като Pac-Man. Можете ли да идентифицирате четирите типа обекти, изброени по-горе, в тази игра?
✅ Помислете за игра като Pac-Man. Можете ли да разпознаете четирите вида обекти, изброени по-горе в тази игра?
```mermaid
classDiagram
class GameObject {
+x: number
+y: number
+type: string
+exists_somewhere()
}
class MovableObject {
+moveTo(x, y)
+can_move_around()
}
class TemporaryObject {
+lifespan: number
+has_lifespan()
}
class InteractiveObject {
+onCollision()
+reacts_to_stuff()
}
GameObject <|-- MovableObject
GameObject <|-- TemporaryObject
GameObject <|-- InteractiveObject
MovableObject <|-- Hero
MovableObject <|-- Enemy
MovableObject <|-- Bullet
TemporaryObject <|-- PowerUp
TemporaryObject <|-- Explosion
InteractiveObject <|-- Collectible
InteractiveObject <|-- Obstacle
```
### Изразяване на поведение чрез код
Сега, когато разбирате общите поведения, които споделят игровите обекти, нека разгледаме как да внедрим тези поведения в JavaScript. Можете да изразите поведението на обектите чрез методи, прикрепени към класове или индивидуални обекти, и има няколко подхода, от които да избирате.
Сега, след като разбирате общите поведения, които споделят игровите обекти, нека разгледаме как да имплементираме тези поведения в JavaScript. Можете да изразите поведението на обект чрез методи, прикачени към класове или отделни обекти, а има няколко подхода за избор.
**Подход, базиран на класове**
**Подходът базиран на класове**
Класовете и наследяването предоставят структурирано решение за организиране на игровите обекти. Подобно на таксономичната класификационна система, разработена от Карл Линей, започвате с базов клас, съдържащ общи свойства, след което създавате специализирани класове, които наследяват тези основи, като добавят специфични способности.
Класовете и наследяването предоставят структурен подход за организиране на игрови обекти. Подобно на таксономичната система разработена от Карл Линей, започвате с базов клас, съдържащ общи свойства, след което създавате специализирани класове, които наследяват тези основи, като добавят специфични възможности.
✅ Наследяването е важна концепция за разбиране. Научете повече от [статията на MDN за наследяването](https://developer.mozilla.org/docs/Web/JavaScript/Inheritance_and_the_prototype_chain).
✅ Наследяването е важна концепция за разбиране. Научете повече в [статията на MDN за наследяване](https://developer.mozilla.org/docs/Web/JavaScript/Inheritance_and_the_prototype_chain).
Ето как можете да внедрите игрови обекти, използвайки класове и наследяване:
Ето как можете да имплементирате игрови обекти, използвайки класове и наследяване:
```javascript
// Step 1: Create the base GameObject class
// Стъпка 1: Създайте базовия клас GameObject
class GameObject {
constructor(x, y, type) {
this.x = x;
@ -63,19 +146,19 @@ class GameObject {
}
```
**Нека разгледаме това стъпка по стъпка:**
**Нека разбием това стъпка по стъпка:**
- Създаваме основен шаблон, който всеки игрови обект може да използва
- Конструкторът запазва местоположението на обекта (`x`, `y`) и какъв тип е той
- Това става основата, върху която ще се изграждат всички ваши игрови обекти
- Конструкторът записва къде се намира обектът (`x`, `y`) и какъв е типът му
- Това става основата, върху която ще строят всички ваши игрови обекти
```javascript
// Step 2: Add movement capability through inheritance
// Стъпка 2: Добавяне на възможност за движение чрез наследяване
class Movable extends GameObject {
constructor(x, y, type) {
super(x, y, type); // Call parent constructor
super(x, y, type); // Извикване на конструктора на родителския клас
}
// Add the ability to move to a new position
// Добавяне на възможност за преместване на нова позиция
moveTo(x, y) {
this.x = x;
this.y = y;
@ -83,47 +166,47 @@ class Movable extends GameObject {
}
```
**В горното сме:**
**В горния код сме:**
- **Разширили** класа GameObject, за да добавим функционалност за движение
- **Извикали** родителския конструктор, използвайки `super()`, за да инициализираме наследените свойства
- **Извикали** конструктора на родителя с`super()` за инициализиране на наследените свойства
- **Добавили** метод `moveTo()`, който обновява позицията на обекта
super(x, y, 'Tree'); // Дърветата не се нуждаят от движение
}
}
// Step 4: Use your game objects
// Стъпка 4: Използвайте вашите игрови обекти
const hero = new Hero(0, 0);
hero.moveTo(5, 5); // Hero can move!
hero.moveTo(5, 5); // Героят може да се движи!
const tree = new Tree(10, 15);
// tree.moveTo() would cause an error - trees can't move
// tree.moveTo() би причинило грешка - дърветата не могат да се движат
```
**Разбиране на тези концепции:**
- **Създава** специализирани типове обекти, които наследяват подходящи поведения
- **Създава** специализирани типове обекти, които наследяват подходящо поведение
- **Демонстрира** как наследяването позволява селективно включване на функции
- **Показва**, че героите могат да се движат, докато дърветата остават неподвижни
- **Показва** че героите могат да се движат, докато дърветата са неподвижни
- **Илюстрира** как йерархията на класовете предотвратява неподходящи действия
✅ Отделете няколко минути, за да си представите герой от Pac-Man (например Inky, Pinky или Blinky) и как би изглеждал в JavaScript.
✅ Отделете няколко минути да си представите как би бил написан герой от Pac-Man (напр. Инки, Пинки или Блинки) на JavaScript.
**Подходът на композиция**
**Подходът с композиция**
Композицията следва философията на модулния дизайн, подобно на това как инженерите проектират космически кораби с взаимозаменяеми компоненти. Вместо да наследявате от родителски клас, комбинирате специфични поведения, за да създадете обекти с точно необходимата функционалност. Този подход предлага гъвкавост без твърди йерархични ограничения.
Композицията следва модулна дизайнерска философия, подобно на начина, по който инженерите проектират космически кораби с взаимнозаменяеми компоненти. Вместо дасе наследявате от родителски клас, комбинирате специфични поведения, за да създадете обекти с точно функционалността, от която се нуждаят. Този подход предлага гъвкавост без стриктни йерархични ограничения.
```javascript
// Step 1: Create base behavior objects
// Стъпка 1: Създайте основни обекти за поведение
const gameObject = {
x: 0,
y: 0,
@ -139,15 +222,15 @@ const movable = {
```
**Ето какво прави този код:**
- **Определя** базов `gameObject`с свойства за позиция и тип
- **Създава** отделен обект за поведение `movable`с функционалност за движение
- **Разделя** отговорностите, като държи данните за позицията и логиката за движение независими
- **Дефинира** основен `gameObject`с позиция и тип
- **Създава** отделен обект поведение `movable`с функция за движение
- **Разделя** отговорностите, като запазва данните за позиция и логиката за движение независими
```javascript
// Step 2: Compose objects by combining behaviors
// Стъпка 2: Създайте обекти чрез комбиниране на поведения
// Step 3: Create factory functions for different object types
// Стъпка 3: Създайте фабрични функции за различни типове обекти
function createHero(x, y) {
return {
...movableObject,
@ -167,68 +250,127 @@ function createStatic(x, y, type) {
}
```
**В горното сме:**
- **Комбинирали** основните свойства на обекта с поведението за движение, използвайки синтаксис за разпръскване
- **Създали** фабрични функции, които връщат персонализирани обекти
- **Позволили** гъвкаво създаване на обекти без твърди йерархии на класовете
- **Позволили** на обектите да имат точно необходимите им поведения
**В горния код сме:**
- **Комбинирали** свойствата на базовия обект с поведението за движение с помощта на spread синтаксис
- **Създавали** фабрични функции, които връщат персонализирани обекти
- **Позволили** гъвкаво създаване на обекти без стриктна йерархия на класовете
- **Дали** възможност обектите да имат точно необходимите им поведения
```javascript
// Step 4: Create and use your composed objects
// Стъпка 4: Създайте и използвайте вашите композирани обекти
const hero = createHero(10, 10);
hero.moveTo(5, 5); // Works perfectly!
hero.moveTo(5, 5); // Работи перфектно!
const tree = createStatic(0, 0, 'Tree');
// tree.moveTo() is undefined - no movement behavior was composed
// tree.moveTo() не е дефинирано - не е композирано поведение за движение
```
**Основни точки за запомняне:**
- **Комбинира** обекти чрез смесване на поведения, вместо да ги наследява
- **Осигурява** повече гъвкавост от твърдите йерархии на наследяване
- **Позволява** на обектите да имат точно необходимите им функции
- **Използва** модерен синтаксис за разпръскване в JavaScript за чисто комбиниране на обекти
**Ключови точки за запомняне:**
- **Комбинира** обекти чрез смесване на поведения, а не чрез наследяване
- **Осигурява** повече гъвкавост от стриктните йерархии на наследяване
- **Позволява** обектите да имат точно необходимите си функции
- **Използва** модерен JavaScript spread синтаксис за чисто комбиниране на обекти
```
**Which Pattern Should You Choose?**
> 💡 **Pro Tip**: Both patterns have their place in modern JavaScript development. Classes work well for clearly defined hierarchies, while composition shines when you need maximum flexibility.
>
**Here's when to use each approach:**
- **Choose** inheritance when you have clear "is-a" relationships (a Hero *is-a* Movable object)
- **Select** composition when you need "has-a" relationships (a Hero *has* movement abilities)
- **Consider** your team's preferences and project requirements
- **Remember** that you can mix both approaches in the same application
## Communication Patterns: The Pub/Sub System
As applications grow complex, managing communication between components becomes challenging. The publish-subscribe pattern (pub/sub) solves this problem using principles similar to radio broadcasting – one transmitter can reach multiple receivers without knowing who's listening.
Consider what happens when a hero takes damage: the health bar updates, sound effects play, visual feedback appears. Rather than coupling the hero object directly to these systems, pub/sub allows the hero to broadcast a "damage taken" message. Any system that needs to respond can subscribe to this message type and react accordingly.
**Which Pattern Should You Choose?**
✅ **Pub/Sub** stands for 'publish-subscribe'
```mermaid
quadrantChart
title Code Organization Patterns
x-axis Simple --> Complex
y-axis Rigid --> Flexible
quadrant-1 Advanced Composition
quadrant-2 Hybrid Approaches
quadrant-3 Basic Inheritance
quadrant-4 Modern Composition
Class Inheritance: [0.3, 0.2]
Interface Implementation: [0.6, 0.4]
Mixin Patterns: [0.7, 0.7]
Pure Composition: [0.8, 0.9]
Factory Functions: [0.5, 0.8]
Prototype Chain: [0.4, 0.3]
```
### Understanding the Pub/Sub Architecture
> 💡 **Професионален съвет**: И двата модела имат място в съвременната JavaScript разработка. Класовете работят добре при ясно дефинирани йерархии, докато композицията блести, когато ви трябва максимална гъвкавост.
>
**Ето кога да използвате всеки подход:**
- **Изберете** наследяване, когато имате ясни "е-един-от" отношения (например герой *е-един-от* подвижен обект)
- **Изберете** композиция, когато имате "има" отношения (например герой *има* способности за движение)
- **Вземете под внимание** предпочитанията на екипа и изискванията на проекта
- **Помнете**, че можете да смесвате двата подхода в едно приложение
### 🔄 **Педагогическа проверка**
**Разбиране на организацията на обекти**: Преди да преминете към комуникационни модели, уверете се, че можете:
- ✅ Да обясните разликата между наследяване и композиция
- ✅ Да определите кога да използвате класове срещу фабрични функции
- ✅ Да разберете как ключовата дума `super()` работи в наследяването
- ✅ Да разпознаете предимствата на всеки подход за разработка на игри
**Бърз самотест**: Как бихте създали летящ враг, който може както да се движи, така и да лети?
- **Подход с наследяване**: `class FlyingEnemy extends Movable`
- **Подход с композиция**: `{ ...movable, ...flyable, ...gameObject }`
**Връзка с реалния свят**: Тези модели се използват навсякъде:
- **React компоненти**: Props (композиция) срещу наследяване на класове
- **Игрови двигатели**: Entity-component системи използват композиция
- **Мобилни приложения**: UI фреймуъркове често използват йерархии на наследяване
## Комуникационни модели: Системата Pub/Sub
С нарастването на сложността на приложенията, управлението на комуникацията между компонентите става предизвикателство. Моделът publish-subscribe (pub/sub) решава този проблем, използвайки принципи, подобни на радиопредаване – един предавател може да достигне множество приемници, без да знае кой слуша.
Помислете какво се случва, когато герой получи щета: лентата за здраве се обновява, звукови ефекти звучат, визуална обратна връзка се появява. Вместо да свързвате герой обекта директно с тези системи, pub/sub позволява на героя да излъчи съобщение „взета щета“. Всяка система, която трябва да реагира, може да се абонира за този тип съобщение и да реагира съответно.
✅ **Pub/Sub** означава 'публикувай-абонирай се'
```mermaid
flowchart TD
A[Геройът Получава Щети] --> B[Публикуване: HERO_DAMAGED]
B --> C[Система за Събития]
C --> D[Абонат Лента за Здраве]
C --> E[Абонат Звукова Система]
C --> F[Абонат Визуални Ефекти]
C --> G[Абонат Система за Постижения]
D --> H[Обновяване на Показанията за Здраве]
E --> I[Възпроизвеждане на Звук за Щета]
F --> J[Показване на Червен Мигане]
G --> K[Проверка на Постиженията за Оцеляване]
style A fill:#ffebee
style B fill:#e1f5fe
style C fill:#e8f5e8
style H fill:#fff3e0
style I fill:#fff3e0
style J fill:#fff3e0
style K fill:#fff3e0
```
### Разбиране на архитектурата Pub/Sub
The pub/sub pattern keeps different parts of your application loosely coupled, meaning they can work together without being directly dependent on each other. This separation makes your code more maintainable, testable, and flexible to changes.
Моделът pub/sub държи различните части на приложението ви слабо свързани, което означава, че те могат да работят заедно без да са пряко зависими една от друга. Това разделяне прави кода ви по-лесен за поддръжка, тестване и по-гъвкав към промени.
**The key players in pub/sub:**
- **Messages**– Simple text labels like `'PLAYER_SCORED'` that describe what happened (plus any extra info)
- **Publishers**– The objects that shout out "Something happened!" to anyone who's listening
- **Subscribers**– The objects that say "I care about that event" and react when it happens
- **Event System**– The middleman that makes sure messages get to the right listeners
**Основните играчи в pub/sub:**
- **Съобщения** – Прости текстови етикети като `'PLAYER_SCORED'`, които описват какво сее случило (плюс допълнителна информация)
- **Публикуващи** – Обекти, които викат „Нещо се случи!“ на всеки, който слуша
- **Абонати** – Обекти, които казват „Интересувам се от това събитие“ и реагират при настъпването му
- **Система за събития** – Съединителят, който гарантира, че съобщенията достигат до правилните слушатели
### Building an Event System
### Създаване на система за събития
Let's create a simple but powerful event system that demonstrates these concepts:
Нека създадем проста, но мощна система за събития, която демонстрира тези концепции:
```javascript
// Step 1: Create the EventEmitter class
// Стъпка 1: Създайте класа EventEmitter
class EventEmitter {
constructor() {
this.listeners = {}; // Store all event listeners
this.listeners = {}; // Съхранявайте всички слушатели на събития
}
// Register a listener for a specific message type
// Регистрирайте слушател за конкретен тип съобщение
on(message, listener) {
if (!this.listeners[message]) {
this.listeners[message] = [];
@ -236,7 +378,7 @@ class EventEmitter {
this.listeners[message].push(listener);
}
// Send a message to all registered listeners
// Изпратете съобщение до всички регистрирани слушатели
emit(message, payload = null) {
if (this.listeners[message]) {
this.listeners[message].forEach(listener => {
@ -247,37 +389,37 @@ class EventEmitter {
}
```
**Разглеждане на това, което се случва тук:**
- **Създава** централизирана система за управление на събития, използвайки прост клас
- **Съхранява** слушатели в обект, организиран по тип съобщение
- **Регистрира** нови слушатели, използвайки метода `on()`
- **Излъчва** съобщения към всички заинтересовани слушатели, използвайки`emit()`
**Разбиване на това, което се случва тук:**
- **Създава** централизирана система за управление на събитията чрез прост клас
- **Съхранява** слушатели в обект, организиран по типове съобщения
- **Регистрира** нови слушатели чрез метода `on()`
- **Излъчва** съобщения до всички заинтересовани слушатели чрез`emit()`
- **Поддържа** опционални данни за предаване на релевантна информация
### Съчетаване на всичко: Практически пример
### Събиране на всичко: Практически пример
Добре, нека видим това в действие! Ще създадем проста система за движение, която показва колко чист и гъвкав може да бъде pub/sub:
Добре, нека го видим на практика! Ще създадем проста система за движение, която показва колко чист и гъвкав може да бъде pub/sub:
```javascript
// Step 1: Define your message types
// Стъпка 1: Дефинирайте типовете си съобщения
const Messages = {
HERO_MOVE_LEFT: 'HERO_MOVE_LEFT',
HERO_MOVE_RIGHT: 'HERO_MOVE_RIGHT',
ENEMY_SPOTTED: 'ENEMY_SPOTTED'
};
// Step 2: Create your event system and game objects
// Стъпка 2: Създайте вашата система за събития и игрови обекти
const eventEmitter = new EventEmitter();
const hero = createHero(0, 0);
```
**Ето какво прави този код:**
- **Определя** обект с константи, за да предотврати грешки при имената на съобщенията
- **Създава** инстанция на event emitter за управление на цялата комуникация
- **Инициализира** герой на начална позиция
- **Дефинира** обект с константи, за да предотврати грешки при изписване на имена на съобщения
- **Създава** инстанция на event emitter за обработка на цялата комуникация
- **Инициализира** герой обект на началната позиция
```javascript
// Step 3: Set up event listeners (subscribers)
// Стъпка 3: Настройте слушатели на събития (абонати)
eventEmitter.on(Messages.HERO_MOVE_LEFT, () => {
hero.moveTo(hero.x - 5, hero.y);
console.log(`Hero moved to position: ${hero.x}, ${hero.y}`);
- **Свързва** входа от клавиатурата със събитията в играта без силно свързване
- **Позволява** на системата за вход да комуникира с игровите обекти индиректно
- **Позволява** множество системи да реагират на едни и същи събития от клавиатурата
- **Улеснява** промяната на клавишните комбинации или добавянето на нови методи за вход
> 💡 **Полезен съвет**: Красотата на този модел е в неговата гъвкавост! Можете лесно да добавите звукови ефекти, трептене на екрана или частици, като просто добавите още слушатели на събития – без да се налага да променяте съществуващия код за клавиатура или движение.
- **Свързва** клавиатурния вход с игрови събития без стегната връзка
- **Позволява** на системата за вход да комуникира с игрови обекти непряко
- **Да позволява** множество системи да реагират на едни и същи клавиатурни събития
- **Прави** лесно променянето на клавишните настройки или добавянето на нови методи за вход
```mermaid
sequenceDiagram
participant User
participant Keyboard
participant EventEmitter
participant Hero
participant SoundSystem
participant Camera
User->>Keyboard: Натиска ArrowLeft
Keyboard->>EventEmitter: emit('HERO_MOVE_LEFT')
EventEmitter->>Hero: Премести наляво с 5 пиксела
EventEmitter->>SoundSystem: Възпроизвеждане на звук от стъпки
EventEmitter->>Camera: Следи героя
Hero->>Hero: Актуализиране на позицията
SoundSystem->>SoundSystem: Възпроизвеждане на звук
Camera->>Camera: Коригира изгледа
```
> 💡 **Професионален съвет**: Красотата на този модел е в гъвкавостта! Лесно можете да добавите звукови ефекти, разклащане на екрана или ефекти с частици, просто добавяйки още слушатели на събития – без нужда да модифицирате съществуващия код за клавиатура или движение.
>
**Ето защо ще харесате този подход:**
- Добавянето на нови функции става изключително лесно – просто слушайте събитията, които ви интересуват
- Множество неща могат да реагират на едно и също събитие, без да си пречат
- Тестването става много по-лесно, защото всяка част работи независимо
- Когато нещо се обърка, знаете точно къде да търсите
- Добавянето на нови функции става много лесно – просто слушайте събитията, които ви интересуват
- Множество елементи могат да реагират на едно и също събитие без да си пречат
- Тестовете са много по-лесни, защото всяка част работи независимо
- Когато нещо сесчупи, знаете точно къде да търсите
### Защо Pub/Sub мащабира ефективно
Моделът pub/sub запазва простотата, докато приложенията стават по-сложни. Независимо дали управлявате десетки врагове, динамични актуализации на потребителския интерфейс или звукови системи, моделът се справя с увеличаването на мащаба без архитектурни промени. Новите функции се интегрират в съществуващата система за събития, без да засягат установената функционалност.
Моделът pub/sub запазва простотата, докато приложенията растат в сложност. Независимо дали управлявате десетки врагове, динамични UI обновявания или звукови системи, моделът обработва увеличаващия се мащаб без архитектурни промени. Новите функции се интегрират в съществуващата система за събития без да повлияват на установената функционалност.
> ⚠️ **Честа грешка**: Не създавайте твърде много специфични типове съобщения в началото. Започнете с широки категории и ги уточнявайте, когато нуждите на играта станат по-ясни.
> ⚠️ **Честа грешка**: Не създавайте твърде много специфични типове съобщения в началото. Започнете с широки категории и ги уточнявайте, когато нуждите на вашата игра станат по-ясни.
>
**Най-добри практики за следване:**
- **Групирайте** свързани съобщения в логически категории
- **Използвайте** описателни имена, които ясно показват какво сее случило
- **Поддържайте** простота и фокусираност на данните в съобщенията
- **Документирайте** типовете съобщения за сътрудничество в екипа
**Добри практики, които да следвате:**
- **Групирайте** свързаните съобщения в логически категории
- **Използвайте** описателни имена, които ясно указват какво сее случило
- **Поддържайте** полезния товар на съобщенията прост и фокусиран
- **Документирайте** типовете съобщения за екипна колаборация
### 🔄 **Педагогическа проверка**
**Разбиране на архитектурата, управлявана от събития**: Проверете разбирането си на цялата система:
- ✅ Как моделът pub/sub предотвратява стегнати връзки между компонентите?
- ✅ Защо е по-лесно да добавяте нови функции със събитийно-ориентирана архитектура?
- ✅ Каква роля играе EventEmitter в потока на комуникацията?
- ✅ Как константите за съобщенията предотвратяват грешки и подобряват поддръжката?
**Дизайнерско предизвикателство**: Как бихте управлявали тези игрови сценарии с pub/sub?
1. **Враг умира**: Обновяване на резултата, пускане на звук, появяване на power-up, премахване от екрана
2. **Завършен ниво**: Спиране на музиката, показване на UI, запазване на прогрес, зареждане на следващото ниво
3. **Събран power-up**: Подобряване на умения, обновяване на UI, пускане на ефект, стартиране на таймер
**Професионална връзка**: Този модел се използва в:
- **Frontend фреймуъркове**: React/Vue системи за събития
- **Backend услуги**: Микросервизни комуникации
- **Игрови двигатели**: Системата за събития на Unity
- **Мобилна разработка**: Системи за известия в iOS/Android
---
## Предизвикателство с GitHub Copilot Agent 🚀
## Предизвикателство GitHub Copilot Agent 🚀
Използвайте режим Agent, за да завършите следното предизвикателство:
**Описание:** Създайте проста система за игрови обекти, използвайки както наследяване, така и модела pub/sub. Ще внедрите основна игра, в която различни обекти могат да комуникират чрез събития, без да знаят директно един за друг.
**Описание:** Създайте проста система за игрови обекти, използваща както наследяване, така и модела pub/sub. Ще реализирате базова игра, в която различни обекти могат да комуникират чрез събития, без да се познават директно.
**Задача:** Създайте система за игра на JavaScript със следните изисквания: 1) Създайте базов клас GameObject с x, y координати и свойство за тип. 2) Създайте клас Hero, който разширява GameObject и може да се движи. 3) Създайте клас Enemy, който разширява GameObject и може да преследва героя. 4) Внедрете клас EventEmitter за модела pub/sub. 5) Настройте слушатели на събития, така че когато героят се движи, близките врагове да получават събитие 'HERO_MOVED' и да обновяват позицията си, за да се придвижат към героя. Включете console.log изявления, за да покажете комуникацията между обектите.
**Подсказка:** Създайте JavaScript игрова система със следните изисквания: 1) Създайте базов клас GameObject с координати x, y и свойство тип. 2) Създайте клас Hero, който наследява GameObject и може да се движи. 3) Създайте клас Enemy, който наследява GameObject и може да преследва героя. 4) Реализирайте клас EventEmitter за модела pub/sub. 5) Настройте слушатели на събития така, че когато геройсе движи, близките врагове получават събитие 'HERO_MOVED' и актуализират позицията си, за да се движат към героя. Включете изход в конзолата, за да показвате комуникацията между обектите.
Научете повече за [режим Agent](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
Научете повече за [режим agent](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
## 🚀 Предизвикателство
Обмислете как моделът pub-sub може да подобри архитектурата на играта. Определете кои компоненти трябва да излъчват събития и как системата трябва да реагира. Проектирайте концепция за игра и очертайте комуникационните модели между нейните компоненти.
Научете повече за Pub/Sub като [прочетете за него](https://docs.microsoft.com/azure/architecture/patterns/publisher-subscriber/?WT.mc_id=academic-77807-sagibbon).
### ⚡ **Какво можете да направите през следващите 5 минути**
- [ ] Отворете всяка онлайн HTML5 игра и инспектирайте кода ѝ с DevTools
- [ ] Създайте прост HTML5 Canvas елемент и нарисувайте базова форма
- [ ] Опитайте да използвате `setInterval` за създаване на прост анимационен цикъл
- [ ] Разгледайте документацията на Canvas API и опитайте някой метод за рисуване
### 🎯 **Какво можете да постигнете този час**
- [ ] Завършете теста след урока и разберете концепциите за разработка на игри
- [ ] Настройте структурата на проекта за вашата игра с HTML, CSS и JavaScript файлове
- [ ] Създайте основен геймплей цикъл, който обновява и изобразява непрекъснато
- [ ] Нарисувайте първите си игрови спрайтове върху канваса
- [ ] Имплементирайте основно зареждане на ресурси за изображения и звуци
### 📅 **Вашият седмичен процес по създаване на игра**
- [ ] Завършете цялата космическа игра с всички планирани функции
- [ ] Създайте система за резултати и проследяване на напредъка на играча
- [ ] Направете играта си отзивчива и достъпна на различни устройства
- [ ] Споделете играта си онлайн и съберете обратна връзка от играчите
### 🌟 **Вашият месечен процес за разработка на игри**
- [ ] Създайте няколко игри изследващи различни жанрове и механики
- [ ] Научете игрови framework като Phaser или Three.js
- [ ] Приносете към проекти с отворен код за разработка на игри
- [ ] Усъвършенствайте напреднали модели за програмиране на игри и оптимизация
- [ ] Създайте портфолио, демонстриращо вашите умения по разработка на игри
- [ ] Наставлявайте други, интересуващи се от разработка на игри и интерактивни медии
## 🎯 Вашата времева линия за майсторство в разработката на игри
```mermaid
timeline
title Прогрес в усвояването на архитектурата на игрите
section Обектни шаблони (20 минути)
Организация на кода: Наследяване на класове
: Шаблони за композиция
: Фабрични функции
: Смесване на поведения
section Комуникационни системи (25 минути)
Архитектура на събития: Имплементация на Pub/Sub
: Дизайн на съобщения
: Емитери на събития
: Слаба свързаност
section Дизайн на игрови обекти (30 минути)
Системи на обекти: Управление на свойства
: Композиция на поведение
: Обработка на състояния
: Управление на жизнения цикъл
section Архитектурни шаблони (35 минути)
Дизайн на системи: Системи с компоненти
: Наблюдателен шаблон
: Команден шаблон
: Машини на състоянията
section Разширени концепции (45 минути)
Масшабируема архитектура: Оптимизация на производителността
: Управление на паметта
: Модулен дизайн
: Стратегии за тестиране
section Концепции за игрови двигатели (1 седмица)
Професионално развитие: Сценични графове
: Управление на активи
: Рендъринг пайплайни
: Интеграция на физика
section Майсторство в рамките (2 седмици)
Модерен гейм девелъпмънт: React гейм шаблони
: Оптимизация на Canvas
: Основи на WebGL
: PWA игри
section Практики в индустрията (1 месец)
Професионални умения: Сътрудничество в екип
: Прегледи на код
: Игрови дизайн шаблони
: Профилиране на производителността
```
### 🛠️ Резюме на вашия комплект за архитектура на игри
Помислете как моделът pub-sub може да подобри архитектурата на играта. Идентифицирайте кои компоненти трябва да излъчват събития и как системата трябва да реагира. Проектирайте концепция за игра и начертайте комуникационните модели между нейните компоненти.
След завършване на този урок, вече имате:
- **Майсторство на дизайн патерни**: Разбиране на компромисите между наследяване и композиция
- **Събитийно-ориентирана архитектура**: Имплементация на pub/sub за мащабируема комуникация
- **Обектно-ориентиран дизайн**: Класови йерархии и поведение чрез композиция
- **Модерен JavaScript**: Фабрични функции, spread синтаксис и ES6+ модели
- **Мащабируема архитектура**: Принципи за слабо свързване и модулен дизайн
- **Основи на разработка на игри**: Системи с ентити и компонентни модели
- **Професионални модели**: Стандартизирани подходи за организация на кода
## Следлекционен тест
**Приложения в реалния свят**: Тези модели се прилагат директно в:
- **Frontend фреймуъркове**: React/Vue архитектура на компоненти и управление на състоянието
- **Backend услуги**: Комуникация между микросървиси и събитийно-ориентирани системи
- **Мобилна разработка**: Архитектура на iOS/Android приложения и системи за известия
- **Игрални енджини**: Unity, Unreal и уеб-базирана разработка на игри
- **Корпоративен софтуер**: Event sourcing и дизайн на разпределени системи
- **API дизайн**: RESTful услуги и комуникация в реално време
**Професионални умения, придобити от вас**: Вече можете:
- **Проектиране** на мащабируеми софтуерни архитектури с доказани модели
- **Имплементиране** на събитийно-ориентирани системи, които управляват сложни взаимодействия
- **Избор** на подходящи стратегии за организация на кода според различни ситуации
- **Отстраняване на проблеми** и поддръжка на слабо свързани системи ефективно
- **Комуникация** на технически решения с използване на индустриално стандартизирана терминология
## Преглед и самостоятелно обучение
**Следващо ниво**: Готови сте да имплементирате тези модели в реална игра, да изследвате напреднали теми за разработка на игри или да приложите тези архитектурни концепции в уеб приложения!
Научете повече за Pub/Sub, като [прочетете за него](https://docs.microsoft.com/azure/architecture/patterns/publisher-subscriber/?WT.mc_id=academic-77807-sagibbon).
🌟 **Постижение Открито**: Успешно овладяхте фундаментални модели за софтуерна архитектура, които захранват всичко - от прости игри до сложни корпоративни системи!
## Задание
## Assignment
[Създайте макет на игра](assignment.md)
[Mock up a game](assignment.md)
---
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Отказ от отговорност**:
Този документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за недоразумения или погрешни интерпретации, произтичащи от използването на този превод.
Този документ е преведен с помощта на AI преводаческа услуга [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи могат да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Ние не носим отговорност за никакви недоразумения или неправилни интерпретации, произтичащи от използването на този превод.
# Създаване на Космическа Игра Част 2: Рисуване на Герои и Чудовища върху Canvas
API-то на Canvas е една от най-мощните функции в уеб разработката за създаване на динамична, интерактивна графика директно в браузъра. В този урок ще преобразим празния HTML елемент `<canvas>` в игрови свят, изпълнен с герои и чудовища. Помислете за canvas като за вашата дигитална арт дъска, където кодът става визуален.
Ще надградим наученото в предишния урок и ще се потопим във визуалните аспекти. Ще научите как да зареждате и показвате игрови спрайтове, да позиционирате елементи прецизно и да създавате визуалната основа за вашата космическа игра. Това свързва статичните уеб страници с динамични, интерактивни преживявания.
До края на този урок ще имате завършена игрова сцена с правилно позициониран кораб на героя и формации на врагове, готови за битка. Ще разберете как съвременните игри рендират графики в браузъри и ще придобиете умения да създавате свои собствени интерактивни визуални преживявания. Нека изследваме графиките на canvas и да вдъхнем живот на вашата космическа игра!
## Тест преди лекцията
# Изградете космическа игра Част 2: Рисувайте героя и чудовищата върху Canvas
```mermaid
journey
title Вашето графично пътешествие с Canvas
section Основи
Разберете Canvas API: 3: Student
Научете координатната система: 4: Student
Рисувайте основни форми: 4: Student
section Работа с изображения
Заредете игрови ресурси: 4: Student
Обработвайте асинхронно зареждане: 5: Student
Позиционирайте спрайтове: 5: Student
section Игрово изобразяване
Създайте игров екран: 5: Student
Изградете формации: 5: Student
Оптимизирайте производителността: 4: Student
```
Canvas API е една от най-мощните функции в уеб разработката за създаване на динамична, интерактивна графика директно в браузъра ви. В този урок ще превърнем празния HTML `<canvas>` елемент в игров свят, пълен с герои и чудовища. Мислете за canvas като за вашето дигитално художествено платно, където кодът се превръща във визуална графика.
Строим върху това, което научихте в предишния урок, и сега ще навлезем в визуалната част. Ще научите как да зареждате и показвате игрови спрайтове, да позиционирате елементи точно и да създадете визуалната основа за вашата космическа игра. Това създава мост между статичните уеб страници и динамичните, интерактивни преживявания.
В края на този урок ще имате пълна игрова сцена с правилно позициониран вашия герой и вражески формации, готови за битка. Ще разберете как модерните игри рисуват графиката в браузърите и ще придобиете умения за създаване на собствени интерактивни визуални преживявания. Нека изследваме графиката в canvas и да вдъхнем живот на вашата космическа игра!
```mermaid
mindmap
root((Canvas Graphics))
Canvas Element
HTML5 Функция
2D Контекст
Координатна Система
Контрол на Пикселите
Drawing Operations
Основни Форми
Изобразяване на Текст
Показване на Изображение
Рисуване на Пътеки
Asset Management
Зареждане на Изображения
Асинхронни Операции
Обработка на Грешки
Производителност
Game Rendering
Позициониране на Спрайтове
Подредба на Формации
Композиция на Сцената
Актуализации на Кадъра
Visual Effects
Цветове и Стилове
Трансформации
Анимации
Наслагване на Слоеве
```
## Предварителен тест преди лекцията
[Тест преди лекцията](https://ff-quizzes.netlify.app/web/quiz/31)
[Предварителен тест преди лекцията](https://ff-quizzes.netlify.app/web/quiz/31)
## Canvas
Какво точно представлява елементът `<canvas>`? Това е решението на HTML5 за създаване на динамична графика и анимации в уеб браузъри. За разлика от обикновените изображения или видеа, които са статични, canvas ви дава контрол на ниво пиксел върху всичко, което се появява на екрана. Това го прави идеален за игри, визуализация на данни и интерактивно изкуство. Помислете за него като за програмируема повърхност за рисуване, където JavaScript е вашата четка.
И така, какво точно представлява този `<canvas>` елемент? Това е решението на HTML5 за създаване на динамична графика и анимации в уеб браузърите. За разлика от обикновените изображения или видеа, които са статични, canvas ви дава контрол на нивото на пикселите върху всичко, което се появява на екрана. Това го прави перфектен за игри, визуализации на данни и интерактивно изкуство. Мислете го като програмируемо рисувателно платно, където JavaScript е вашата четка.
По подразбиране, елементът canvas изглежда като празен, прозрачен правоъгълник на вашата страница. Но именно тук се крие потенциалът! Истинската му сила се проявява, когато използвате JavaScript за рисуване на форми, зареждане на изображения, създаване на анимации и правене на неща, които реагират на взаимодействията на потребителя. Това е подобно на начина, по който пионерите в компютърната графика от Bell Labs през 60-те години са програмирали всеки пиксел, за да създадат първите цифрови анимации.
По подразбиране, canvas елементът изглежда като празен, прозрачен правоъгълник на страницата ви. Но именно в това крие потенциалът! Истинската му мощ се проявява, когато използвате JavaScript, за да рисувате форми, да зареждате изображения, да създавате анимации и да правите нещата реактивни към действията на потребителя. Това е подобно на начина, по който ранните пионери на компютърната графика в Bell Labs през 60-те години на миналия век трябваше да програмират всеки пиксел, за да създадат първите дигитални анимации.
✅ Прочетете [повече за Canvas API](https://developer.mozilla.org/docs/Web/API/Canvas_API) на MDN.
✅ Прочетете [повече за Canvas API](https://developer.mozilla.org/docs/Web/API/Canvas_API) в MDN.
Ето как обикновено се декларира като част от тялото на страницата:
@ -33,81 +78,155 @@ API-то на Canvas е една от най-мощните функции в у
- **Задава** атрибута `id`, за да можете да се позовавате на този конкретен елемент canvas в JavaScript
- **Определя** ширината в пиксели, за да контролира хоризонталния размер на canvas
- **Установява** височината в пиксели, за да определи вертикалните размери на canvas
## Рисуване на прости геометрични фигури
Сега, когато знаете какво представлява елементът canvas, нека разгледаме как всъщност да рисуваме върху него! Canvas използва координатна система, която може да ви се стори позната от часовете по математика, но има една важна особеност, специфична за компютърната графика.
Canvas използва картезиански координати сос x (хоризонтална) и ос y (вертикална), за да позиционира всичко, което рисувате. Но ето ключовата разлика: за разлика от координатната система от часовете по математика, началната точка `(0,0)` започва в горния ляв ъгъл, като стойностите на x се увеличават, когато се движите надясно, а стойностите на y се увеличават, когато се движите надолу. Този подход датира от ранните компютърни дисплеи, където електронните лъчи сканират отгоре надолу, правейки горния ляв ъгъл естествена начална точка.

**Ето какво прави този код:**
- **Задава** атрибута `id`, за да можете да препращате към този конкретен canvas елемент в JavaScript
- **Определя** `width` в пиксели, за да контролира хоризонталния размер на canvas
- **Установява** `height` в пиксели, за да определи вертикалните размери на canvas
## Рисуване на проста геометрия
Сега, когато знаете какво представлява canvas елементът, нека разгледаме как всъщност да рисуваме върху него! Canvas използва координатна система, която може да ви е позната от часовете по математика, но има една важна особеност, специфична за компютърната графика.
Canvas използва декартова координатна система с x-ос (хоризонтална) и y-ос (вертикална) за позициониране на всичко, което рисувате. Но тук е ключовата разлика: за разлика от координатната система в математиката, началната точка `(0,0)` започва от горния ляв ъгъл, като x-стойностите нарастват, когато се движите надясно, а y-стойностите се увеличават, когато се движите надолу. Този подход произлиза от ранните компютърни дисплеи, където електронният лъч сканираше отгоре надолу, правейки горния ляв ъгъл естествена начална точка.
```mermaid
quadrantChart
title Система от координати на платното
x-axis Ляво --> Дясно
y-axis Горна --> Долна
quadrant-1 Четвърт 1
quadrant-2 Четвърт 2
quadrant-3 Четвърт 3
quadrant-4 Четвърт 4
Origin Point: [0.1, 0.1]
Hero Center: [0.5, 0.8]
Enemy Formation: [0.3, 0.2]
Power-up: [0.7, 0.6]
UI Elements: [0.9, 0.1]
```

> Изображение от [MDN](https://developer.mozilla.org/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes)
За да рисувате върху елемента canvas, ще следвате същия тристепенен процес, който формира основата на всички графики на canvas. След като го направите няколко пъти, това става естествено:
1. **Получете референция** към вашия елемент Canvas от DOM (точно както всеки друг HTML елемент)
2. **Получете 2D контекст за рендиране** – това предоставя всички методи за рисуване
3. **Започнете да рисувате!** Използвайте вградените методи на контекста, за да създадете вашата графика
За да рисувате върху canvas елемента, ще следвате същия тристепенен процес, който образува основата на цялата canvas графика. След като го направите няколко пъти, това ще стане втора природа:
```mermaid
flowchart LR
A[HTML Canvas елемент] --> B[Вземи препратка към Canvas]
B --> C[Вземи 2D контекст]
C --> D[Операции по рисуване]
D --> E[Рисуване на форми]
D --> F[Рисуване на текст]
D --> G[Рисуване на изображения]
D --> H[Прилагане на стилове]
E --> I[Рендиране на екрана]
F --> I
G --> I
H --> I
style A fill:#e1f5fe
style C fill:#e8f5e8
style I fill:#fff3e0
```
1. **Вземете препратка** към вашия Canvas елемент от DOM (като всеки друг HTML елемент)
2. **Вземете 2D рендеринг контекст** – това предоставя всички методи за рисуване
3. **Започнете да рисувате!** Използвайте вградените методи на контекста, за да създадете графиката си
// Стъпка 3: Задайте цвета за запълване и нарисувайте правоъгълник
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, 200, 200); // x, y, width, height
ctx.fillRect(0, 0, 200, 200); // x, y, ширина, височина
```
**Нека разгледаме това стъпка по стъпка:**
- **Вземаме** нашия елемент canvas, използвайки неговия ID, и го съхраняваме в променлива
- **Получаваме** 2D контекст за рендиране – това е нашият инструментариум, пълен с методи за рисуване
- **Указваме** на canvas, че искаме да запълним нещата с червено, използвайки свойството `fillStyle`
- **Рисуваме** правоъгълник, започващ от горния ляв ъгъл (0,0), който е широк и висок 200 пиксела
✅ Canvas API се фокусира предимно върху 2D форми, но можете също така да рисувате 3D елементи на уеб сайт; за това може да използвате [WebGL API](https://developer.mozilla.org/docs/Web/API/WebGL_API).
**Нека разчленим това стъпка по стъпка:**
- **Вземаме** канваса чрез неговия ID и го съхраняваме в променлива
- **Вземаме** 2D рендеринг контекста – това е нашият комплект с инструменти с методи за рисуване
- **Указваме** на canvas да запълва с червен цвят чрез свойството `fillStyle`
- **Рисуваме** правоъгълник, започващ от горния ляв ъгъл (0,0) с ширина и височина 200 пиксела
Можете да рисувате всякакви неща с Canvas API като:
✅ Canvas API основно се фокусира върху 2D форми, но можете също да рисувате 3D елементи в уебсайт; за това може да използвате [WebGL API](https://developer.mozilla.org/docs/Web/API/WebGL_API).
- **Геометрични фигури**, вече показахме как да нарисувате правоъгълник, но има много повече, което можете да нарисувате.
- **Текст**, можете да нарисувате текст с какъвто и да е шрифт и цвят, който пожелаете.
- **Изображения**, можете да нарисувате изображение, базирано на актив като .jpg или .png например.
Можете да рисувате всякакви неща с Canvas API, като например:
✅ Опитайте! Знаете как да нарисувате правоъгълник, можете ли да нарисувате кръг на страницата? Разгледайте някои интересни рисунки с Canvas в CodePen. Ето един [особено впечатляващ пример](https://codepen.io/dissimulate/pen/KrAwx).
- **Геометрични фигури**, вече сме показали как да рисуваме правоъгълник, но има много повече неща, които можете да нарисувате.
- **Текст**, можете да рисувате текст със всякакъв шрифт и цвят.
- **Изображения**, можете да рисувате изображение, базирано на изображение като .jpg или .png например.
## Зареждане и рисуване на изображение
✅ Опитайте! Знаете как да рисувате правоъгълник, може ли да нарисувате кръг на страницата? Вижте някои интересни рисувания на Canvas в CodePen. Ето един [особено впечатляващ пример](https://codepen.io/dissimulate/pen/KrAwx).
Рисуването на основни форми е полезно за начало, но повечето игри се нуждаят от реални изображения! Спрайтове, фонове и текстури са това, което придава визуална привлекателност на игрите. Зареждането и показването на изображения върху canvas работи по различен начин от рисуването на геометрични фигури, но е лесно, след като разберете процеса.
### 🔄 **Педагогическа проверка**
**Разбиране на основите на Canvas**: Преди да преминете към зареждане на изображения, уверете се, че можете:
- ✅ Да обясните как координатната система на canvas се различава от математическите координати
- ✅ Да разберете тристепения процес на операции за рисуване на canvas
- ✅ Да идентифицирате какво предоставя 2D рендеринг контекста
- ✅ Да опишете как fillStyle и fillRect работят заедно
Трябва да създадем обект `Image`, да заредим файла с изображението (това се случва асинхронно, което означава "на заден план") и след това да го нарисуваме върху canvas, когато е готов. Този подход гарантира, че изображенията ви се показват правилно, без да блокират приложението ви, докато се зареждат.
**Бърз само-тест**: Как бихте нарисували син кръг на позиция (100, 50) с радиус 25?
```javascript
ctx.fillStyle = 'blue';
ctx.beginPath();
ctx.arc(100, 50, 25, 0, 2 * Math.PI);
ctx.fill();
```
### Основно зареждане на изображения
**Методите за рисуване с Canvas, които вече знаете**:
- **fillRect()**: Рисува запълнени правоъгълници
- **fillStyle**: Задава цветове и шаблони
- **beginPath()**: Започва нови пътища за рисуване
- **arc()**: Създава кръгове и криви
## Заредете и нарисувайте изображение
Рисуването на основни форми е полезно за начало, но повечето игри се нуждаят от реални изображения! Спрайтове, фон и текстури са онова, което придава визуалния чар на игрите. Зареждането и показването на изображения върху canvas работи по-различно от рисуването на геометрични фигури, но е лесно след като разберете процеса.
Трябва да създадем обект `Image`, да заредим нашия файл с изображението (това се случва асинхронно, което означава "на заден план"), и след това да го нарисуваме върху canvas, когато е готово. Този подход гарантира, че вашите изображения ще се показват правилно, без да блокират приложението, докато се зареждат.
```mermaid
sequenceDiagram
participant JS as JavaScript
participant Img as Обект изображение
participant Server as Файлов сървър
participant Canvas as Контекст на Canvas
JS->>Img: new Image()
JS->>Img: Задаване на свойство src
Img->>Server: Заявка за изображение
Server->>Img: Връщане на данни за изображението
Img->>JS: Събитие onload
JS->>Canvas: drawImage(img, x, y)
Canvas->>Canvas: Рендиране на екрана
Note over JS,Canvas: Асинхронното зареждане предотвратява блокиране на UI
```
### Основно зареждане на изображение
```javascript
const img = new Image();
img.src = 'path/to/my/image.png';
img.onload = () => {
// Image loaded and ready to be used
// Изображението е заредено и готово за използване
console.log('Image loaded successfully!');
};
```
**Какво се случва в този код:**
- **Създаваме** чисто нов обект Image, за да съхраним нашия спрайт или текстура
- **Указваме** кой файл с изображение да се зареди, като задаваме пътя към източника
- **Слушаме** събитието за зареждане, за да знаем точно кога изображението е готово за използване
**Ето какво се случва в този код:**
- Създаваме нов обект Image, който да държи спрайта или текстурата
- Посочваме източника на изображението чрез задаване на пътя
- Слушаме за събитието „load“, за да знаем точно кога изображението е готово за използване
### По-добър начин за зареждане на изображения
### Един по-добър начин за зареждане на изображения
Ето по-стабилен начин за обработка на зареждането на изображения, който професионалните разработчици често използват. Ще обгърнем логиката за зареждане на изображения във функция, базирана на Promise – този подход, популяризиран, когато JavaScript Promises станаха стандарт в ES6, прави кода ви по-организиран и обработва грешките по-елегантно:
Ето един по-стабилен начин за зареждане на изображения, който професионалните разработчици често използват. Обграждаме зареждането на изображение във функция базирана на Promise – този подход, станал популярен с появата на JavaScript Promises в ES6, прави кода ви по-организиран и обработва грешките по-елегантно:
@ -163,32 +282,56 @@ async function renderGameScreen() {
}
```
**Нека разгледаме това стъпка по стъпка:**
- **Зареждаме** както изображенията на героя, така и на чудовището на заден план, използвайки await
- **Вземаме** нашия елемент canvas и получаваме необходимия 2D контекст за рендиране
- **Позиционираме** изображението на героя точно в центъра, използвайки бърза координатна математика
- **Поставяме** изображението на чудовището в горния ляв ъгъл, за да започнем формацията на врага
- **Улавяме** всякакви грешки, които могат да се случат по време на зареждането или рендирането
## Време е да започнете да изграждате вашата игра
**Нека преминем през това стъпка по стъпка:**
- Зареждаме както изображението на героя, така и на чудовището на заден план с await
- Вземаме canvas елемента и нужния 2D рендеринг контекст
- Позиционираме образа на героя точно в центъра, използвайки бързи изчисления с координатите
- Поставяме изображението на чудовището в горния ляв ъгъл, за да започнем формацията на враговете
- Хващаме евентуални грешки, които могат да възникнат по време на зареждането или изобразяването
```mermaid
flowchart TD
A[Зареждане на ресурси] --> B{Всички изображения заредени?}
B -->|Не| C[Показване на зареждане]
B -->|Да| D[Вземане на контекста на канвас]
C --> B
D --> E[Изчистване на екрана]
E --> F[Рисуване на фон]
F --> G[Рисуване на формация на врага]
G --> H[Рисуване на кораба герой]
H --> I[Прилагане на визуални ефекти]
I --> J[Изобразяване на кадър]
subgraph "Веригата за рендериране"
K[Управление на ресурси]
L[Създаване на сцена]
M[Операции по рисуване]
N[Изход на кадър]
end
style A fill:#e1f5fe
style J fill:#e8f5e8
style I fill:#fff3e0
```
## Време е да започнете изграждането на играта
Сега ще съберем всичко заедно, за да създадем визуалната основа на вашата космическа игра. Вече имате солидно разбиране за основите на canvas и техниките за зареждане на изображения, така че тази практическа част ще ви насочи към изграждането на завършен екран на играта с правилно позиционирани спрайтове.
Сега ще обединим всичко, за да създадем визуалната основа на вашата космическа игра. Вече притежавате солидни знания за основите на canvas и техники за зареждане на изображения, така че тази практическа част ще ви преведе през изграждането на пълния гейм екранс правилно позиционирани спрайтове.
### Какво да изградите
Ще създадете уеб страница с елемент Canvas. Тя трябва да рендира черен екран с размери `1024*768`. Предоставили сме ви две изображения:
Ще създадете уеб страница сCanvas елемент. Тя трябва да изобразява черен екран с размери `1024*768`. Ние ви предоставяме две изображения:
- Кораб на героя
- Геройски кораб

### Препоръчителни стъпки за започване на разработката
### Препоръчителни стъпки за започване на разработка
Намерете стартовите файлове, които са създадени за вас в подпапката `your-work`. Структурата на проекта ви трябва да съдържа:
Намерете стартовите файлове, които са създадени за вас в подпапката `your-work`. Структурата на вашия проект трябва да съдържа:
```bash
your-work/
@ -200,46 +343,46 @@ your-work/
└── package.json
```
**С какво разполагате:**
- **Игровите спрайтове** се намират в папката `assets/`, за да остане всичко организирано
- **Вашият основен HTML файл** настройва елемента canvas и подготвя всичко
- **JavaScript файл**, където ще напишете цялата магия за рендиране на играта
**Ето с какво работите:**
- **Игровите спрайтове** се намират в папката `assets/`, за да поддържате всичко организирано
- **Вашият основен HTML файл** настройва canvas елемента и подготвя всичко
- **JavaScript файл**, където ще пишете цялата магия за рендериране на играта
- **package.json**, който настройва сървър за разработка, за да можете да тествате локално
Отворете тази папка във Visual Studio Code, за да започнете разработката. Ще ви е необходима локална среда за разработка с инсталирани Visual Studio Code, NPM и Node.js. Ако нямате `npm` настроен на компютъра си, [ето как да го инсталирате](https://www.npmjs.com/get-npm).
Отворете тази папка във Visual Studio Code, за да започнете разработката. Ще ви трябва локална среда с Visual Studio Code, NPM и Node.js инсталирани. Ако нямате `npm` настроен на компютъра си, [ето как да го инсталирате](https://www.npmjs.com/get-npm).
Стартирайте сървъра за разработка, като навигирате до папката `your-work`:
Стартирайте сървъра за разработка като отидете в папката `your-work`:
```bash
cd your-work
npm start
```
**Тази команда прави някои доста интересни неща:**
- **Стартира** локален сървър на `http://localhost:5000`, за да можете да тествате играта си
- **Сервира** всички ваши файлове правилно, за да може браузърът ви да ги зареди коректно
- **Следи** за промени във файловете ви, за да можете да разработвате гладко
- **Осигурява** професионална среда за разработка, за да тествате всичко
**Тази команда прави няколко много полезни неща:**
- Стартира локален сървър на адрес`http://localhost:5000`, за да може да тествате вашата игра
- Сървира всичките ви файлове правилно, така че браузърът да ги зарежда коректно
- Следи промените във файловете ви, за да разработвате гладко
- Ви дава професионална среда за разработка, за да проверите всичко
> 💡 **Забележка**: Браузърът ви първоначално ще покаже празна страница – това е очаквано! Докато добавяте код, обновявайте браузъра си, за да видите промените. Този итеративен подход към разработката е подобен на начина, по който NASA създаде компютъра за управление на Apollo – тестване на всеки компонент преди интегрирането му в по-голямата система.
> 💡 **Забележка**: Браузърът ви ще покаже празна страница първоначално – това е нормално! Докато добавяте код, обновявайте браузъра, за да видите промените. Този итеративен подход на разработка е подобен на начина, по който НАСАе изграждала компютър за управление на Аполо – тествайки всяка част преди да я интегрира в по-голямата система.
### Добавете код
Добавете необходимия код в `your-work/app.js`, за да изпълните следните задачи:
1. **Нарисувайте canvas с черен фон**
> 💡 **Ето как**: Намерете TODO в `/app.js` и добавете само два реда. Задайте `ctx.fillStyle` на черно, след това използвайте `ctx.fillRect()` започвайки от (0,0) с размерите на вашия canvas. Лесно!
1. **Рисувайте canvas с черен фон**
> 💡 **Ето как**: Намерете TODO в `/app.js` и добавете само две линии. Задайте `ctx.fillStyle` на черно, след което използвайте `ctx.fillRect()` започвайки от (0,0) с размерите на canvas. Лесно!
2. **Заредете текстурите на играта**
> 💡 **Ето как**: Използвайте `await loadAsset()`, за да заредите изображенията на играча и врага. Съхранете ги в променливи, за да можете да ги използвате по-късно. Запомнете – те няма да се покажат, докато всъщност не ги нарисувате!
2. **Заредете игрови текстури**
> 💡 **Ето как**: Използвайте `await loadAsset()` за зареждане на изображението на героя и врага. Запазете ги в променливи, за да ги използвате по-късно. Помнете – те няма да се покажат, докато не ги нарисувате!
3. **Нарисувайте кораба на героя в централно-долна позиция**
> 💡 **Ето как**: Използвайте `ctx.drawImage()`, за да позиционирате героя. За координатата x опитайте с`canvas.width / 2 - 45`, за да го центрирате, а за координатата y използвайте `canvas.height - canvas.height / 4`, за да го поставите в долната част.
3. **Рисувайте кораб на героя в център-долната позиция**
> 💡 **Ето как**: Използвайте `ctx.drawImage()` за позициониране на героя. За x-координатата, пробвайте`canvas.width / 2 - 45`, за да го центрирате, а за y-координатата използвайте `canvas.height - canvas.height / 4`, за да го поставите долу.
4. **Нарисувайте формация от 5×5 вражески кораби**
> 💡 **Ето как**: Намерете функцията `createEnemies` и настройте вложен цикъл. Ще трябва да направите малко математика за разстоянията и позиционирането, но не се притеснявайте – ще ви покажа точно как!
4. **Рисувайте 5×5 формация от вражески кораби**
> 💡 **Ето как**: Намерете функцията `createEnemies` и настройте вложен цикъл. Ще трябва да направите някои изчисления за разстоянията и позиционирането, но не се притеснявайте – ще ви покажа точно как!
Първо, установете константи за правилно оформление на формацията на враговете:
Първо, задайте константи за правилното оформление на вражеската формация:
- **Задаваме** 5 врагове на ред и колона (приятна 5×5 мрежа)
- **Определяме** колко пространство да оставим между враговете, за да не изглеждат претъпкани
- **Изчисляваме** колко широка ще бъде цялата формация
- **Определяме** откъде да започнем и къде да спрем, за да изглежда формацията центрирана
След това създайте вложени цикли, за да нарисувате формацията на враговете:
**Нека разберем какво правят тези константи:**
- Задаваме 5 врагове на ред и колона (уютна 5×5 мрежа)
- Определяме колко разстояние да има между враговете, за да не изглеждат притиснати
- Изчисляваме колко широка ще бъде цялата формация
- Изчисляваме откъде да започнем и къде да свършим, така че формацията да изглежда центрирана
```mermaid
flowchart LR
A["Ширина на платното: 1024px"] --> B["Ширина на формацията: 490px"]
B --> C["Начало X: 267px"]
C --> D["Разстояние между враговете: 98px"]
subgraph "Формация на врагове 5х5"
E["Ред 1: Y=0"]
F["Ред 2: Y=50"]
G["Ред 3: Y=100"]
H["Ред 4: Y=150"]
I["Ред 5: Y=200"]
end
subgraph "Разстояние между колони"
J["Кол 1: X=267"]
K["Кол 2: X=365"]
L["Кол 3: X=463"]
M["Кол 4: X=561"]
N["Кол 5: X=659"]
end
style A fill:#e1f5fe
style B fill:#e8f5e8
style C fill:#fff3e0
```
След това, създайте вложени цикли за рисуване на вражеската формация:
```javascript
for (let x = START_X; x <STOP_X;x+=ENEMY_SPACING){
@ -266,20 +435,39 @@ for (let x = START_X; x < STOP_X; x += ENEMY_SPACING) {
```
**Ето какво прави този вложен цикъл:**
- Външният цикъл **се движи** отляво надясно през формацията
- Вътрешният цикъл **минава** отгоре надолу, за да създаде подредени редове
- **Рисуваме** всеки спрайт на врага на точните x,y координати, които сме изчислили
- Всичко остава **равномерно разположено**, за да изглежда професионално и организирано
- Външният цикъл преминава от ляво надясно през формацията
- Вътрешният цикъл преминава отгоре надолу, за да създаде подредени редове
- Рисуваме всеки враг на точно изчислените x,y координати
- Всичко е равномерно разпределено, за да изглежда професионално и организирано
### 🔄 **Педагогическа проверка**
**Майсторство в рендерирането на играта**: Проверете разбирането си за цялата рендеринг система:
- ✅ Как асинхронното зареждане на изображения предотвратява блокиране на интерфейса при стартиране на играта?
- ✅ Защо изчисляваме позициите на формацията на враговете с помощта на константи, вместо да ги втвърдяваме в кода?
- ✅ Каква роля играе 2D рендеринг контекстът при операциите по рисуване?
- ✅ Как вложените цикли създават организирани спрайт формации?
**Съображения за производителност**: Вашата игра сега демонстрира:
- **Ефективно зареждане на ресурси**: Управление на изображения чрез Promise
- **Организирано рендериране**: Структурирани операции по рисуване
- **Математическо позициониране**: Изчислено разполагане на спрайтове
- **Обработка на грешки**: Меко управление на неуспехи
**Концепции на визуалното програмиране**: Научихте:
- **Координатни системи**: Превръщане на математиката в позиции на екрана
- **Управление на спрайтове**: Зареждане и показване на графики за играта
- **Алгоритми за формации**: Математически модели за организирани разположения
- **Асинхронни операции**: Модерен JavaScript за плавно потребителско изживяване
## Резултат
Завършеният резултат трябва да изглежда така:
Крайният резултат трябва да изглежда така:


## Решение
Опитайте първо сами да решите задачата, но ако се затрудните, погледнете [решението](../../../../6-space-game/2-drawing-to-canvas/solution/app.js).
Моля, опитайте да го решите самите вие първо, но ако се затрудните, разгледайте [решението](../../../../6-space-game/2-drawing-to-canvas/solution/app.js)
---
@ -287,11 +475,150 @@ for (let x = START_X; x < STOP_X; x += ENEMY_SPACING) {
Използвайте режим Agent, за да изпълните следното предизвикателство:
**Описание:** Подобрете canvas на вашата космическа игра, като добавите визуални ефекти и интерактивни елементи, използвайки техниките на Canvas API, които сте научили.
**Задача
**Описание:** Подобрете вашата космическа игра на canvas, като добавите визуални ефекти и интерактивни елементи, използвайки научените техники на Canvas API.
**Задача:** Създайте нов файл на име `enhanced-canvas.html`с canvas, който показва анимирани звезди на заден план, пулсиращ здравен бар за кораба герой и вражески кораби, които бавно се движат надолу. Включете JavaScript код, който рисува блестящи звезди с произволни позиции и прозрачност, реализира здравен бар, който променя цвета си в зависимост от нивото на здраве (зелен > жълт > червен), и анимира враговете да се движат надолу по екрана с различни скорости.
Научете повече за [Agent режим](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
## 🚀 Предизвикателство
Вече сте научили как да рисувате с Canvas API, фокусирано върху 2D; разгледайте [WebGL API](https://developer.mozilla.org/docs/Web/API/WebGL_API) и опитайте да нарисувате 3D обект.
## Квиз след лекцията
[Квиз след лекцията](https://ff-quizzes.netlify.app/web/quiz/32)
## Преглед & Самообучение
Научете повече за Canvas API, като [прочетете за него](https://developer.mozilla.org/docs/Web/API/Canvas_API).
### ⚡ **Какво можете да направите през следващите 5 минути**
- [ ] Отворете конзолата на браузъра и създайте canvas елемент с`document.createElement('canvas')`
- [ ] Опитайте да нарисувате правоъгълник с`fillRect()` върху контекст на canvas
- [ ] Експериментирайте с различни цветове чрез свойството `fillStyle`
- [ ] Нарисувайте прост кръг с метода `arc()`
### 🎯 **Какво можете да постигнете този час**
- [ ] Завършете пост-урочния квиз и разберете основите на canvas
- [ ] Създайте приложение за рисуване върху canvas с различни форми и цветове
- [ ] Реализирайте зареждане на изображения и рендериране на спрайтове за играта
- [ ] Направете проста анимация, която движи обекти по canvas
- [ ] Практикувайте трансформации на canvas като мащабиране, въртене и транслация
### 📅 **Вашето седмично пътешествие с Canvas**
- [ ] Завършете космическата игра с изчистена графика и анимации на спрайтове
- [ ] Усъвършенствайте техники за работа с canvas като градиенти, шарки и композиране
- [ ] Създайте интерактивни визуализации с canvas за представяне на данни
- [ ] Научете оптимизационни техники за плавна производителност
- [ ] Създайте приложение за рисуване или изобразяване с различни инструменти
- [ ] Изследвайте творчески модели за кодиране и генеративно изкуство с canvas
### 🌟 **Вашият месечен път към овладяване на графиката**
- [ ] Изградете сложни визуални приложения с Canvas 2D и WebGL
- [ ] Научете концепции за графично програмиране и основи на шейдъри
- [ ] Допринасяйте за отворени графични библиотеки и инструменти за визуализация
- [ ] Усъвършенствайте оптимизацията на производителността за графично интензивни приложения
- [ ] Създавайте образователно съдържание за програмиране на canvas и компютърна графика
- [ ] Станете експерт по графично програмиране, който помага на други да създават визуални преживявания
## 🎯 Времева линия за овладяване на графиката с Canvas
```mermaid
timeline
title Прогрес на обучението по Canvas API
section Основи на Canvas (15 минути)
Основни операции: Референция към елемент
: Достъп до 2D контекст
: Координатна система
: Рисуване на прости форми
section Техники за рисуване (20 минути)
Графични примитиви: Правоъгълници и кръгове
: Цветове и стилове
: Рендериране на текст
: Операции с пътеки
section Работа с изображения (25 минути)
Управление на ресурси: Създаване на обект изображение
: Асинхронни модели за зареждане
: Обработка на грешки
: Оптимизация на производителността
section Графика за игри (30 минути)
Рендериране на спрайтове: Алгоритми за позициониране
: Изчисляване на формации
: Композиране на сцена
: Рендериране на кадър
section Разширени техники (40 минути)
Визуални ефекти: Трансформации
: Анимации
: Наслагване на слоеве
: Управление на състояния
section Производителност (35 минути)
Оптимизация: Ефективно рисуване
: Управление на паметта
: Контрол на честотата на кадрите
: Кеширане на ресурси
section Професионални умения (1 седмица)
Производствена графика: Интеграция на WebGL
: Canvas библиотеки
: Игрови енджини
: Междуплатформени съображения
section Разширена графика (1 месец)
Специализирани приложения: Визуализация на данни
: Интерактивно изкуство
: Ефекти в реално време
: 3D графика
```
### 🛠️ Обобщение на вашия набор от инструменти за Canvas графика
След завършване на този урок вече имате:
- **Майсторство на Canvas API**: Пълно разбиране на 2D графичното програмиране
- **Координатна математика**: Точно позициониране и алгоритми за разположение
- **Управление на ресурси**: Професионално зареждане на изображения и обработка на грешки
- **Rendering pipeline**: Структуриран подход към композирането на сцени
- **Графика за игри**: Позициониране на спрайтове и изчисляване на формации
- **Асинхронно програмиране**: Модерни JavaScript модели за плавна работа
- **Визуално програмиране**: Превръщане на математически концепции в екранна графика
**Приложения в реалния свят**: Вашите умения с Canvas се използват директно за:
- **Визуализация на данни**: Диаграми, графики и интерактивни табла
- **Разработка на игри**: 2D игри, симулации и интерактивни преживявания
- **Дигитално изкуство**: Творческо кодиране и генеративни арт проекти
- **Дизайн на интерфейси**: Персонализирана графика и интерактивни елементи
- **Образователен софтуер**: Визуални учебни помощници и симулации
- **Уеб приложения**: Динамична графика и визуализации в реално време
**Професионални умения, придобити чрез курса**: Вече можете да:
- **Създавате** персонализирани графични решения без външни библиотеки
- **Оптимизирате** производителността при рендериране за плавно изживяване
- **Отстранявате грешки** при сложни визуални проблеми с инструменти за разработчици
- **Проектирате** скалируеми графични системи с помощта на математически принципи
- **Интегрирате** Canvas графики с модерни уеб рамки
**Методи на Canvas API, които сте усвоили**:
- **Управление на елементи**: getElementById, getContext
- **Операции по рисуване**: fillRect, drawImage, fillStyle
- **Зареждане на активи**: Обекти Image, Promise модели
- **Математическо позициониране**: Изчисления на координати, алгоритми за формации
**Следващо ниво**: Готови сте да добавяте анимации, интерактивност, откриване на сблъсъци или да изследвате WebGL за 3D графика!
🌟 **Постижение отключено**: Построихте цяла система за рендериране на игра, използвайки основни техники на Canvas API!
## Задача
[Играйте с Canvas API](assignment.md)
---
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Отказ от отговорност**:
Този документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Не носим отговорност за недоразумения или погрешни интерпретации, произтичащи от използването на този превод.
Този документ е преведен с помощта на AI преводаческа услуга [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи могат да съдържат грешки или неточности. Оригиналният документ на неговия собствен език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за каквито и да е недоразумения или неправилни тълкувания, произтичащи от използването на този превод.
# Създаване на космическа игра, част 3: Добавяне на движение
Помислете за любимите си игри – това, което ги прави завладяващи, не са само красивите графики, а начинът, по който всичко се движи и реагира на вашите действия. В момента вашата космическа игра е като красива картина, но сега ще добавим движение, което ще я оживи.
Когато инженерите на НАСА програмираха компютъра за управление на мисиите Аполо, те се сблъскаха с подобно предизвикателство: как да накарат космическия кораб да реагира на командите на пилота, като същевременно автоматично поддържа корекции на курса? Принципите, които ще научим днес, отразяват същите концепции – управление на движението, контролирано от играча, заедно с автоматични системни поведения.
В този урок ще научите как да накарате космическите кораби да се движат по екрана, да реагират на командите на играча и да създават плавни модели на движение. Ще разделим всичко на управляеми концепции, които естествено се надграждат една върху друга.
До края ще можете да управлявате героичния си кораб по екрана, докато вражеските кораби патрулират над него. По-важното е, че ще разберете основните принципи, които задвижват системите за движение в игрите.
## Тест преди лекцията
# Създаване на космическа игра Част 3: Добавяне на движение
```mermaid
journey
title Вашето пътешествие в анимацията на играта
section Основи на движението
Разбиране на принципите на движението: 3: Student
Научаване на актуализации на координатите: 4: Student
Реализиране на основно движение: 4: Student
section Контроли на играча
Обработка на клавишни събития: 4: Student
Предотвратяване на стандартни поведения: 5: Student
Създаване на отзивчиви контроли: 5: Student
section Системи на играта
Изграждане на игров цикъл: 5: Student
Управление на жизнения цикъл на обектите: 5: Student
Прилагане на pub/sub модел: 5: Student
```
Помислете за любимите си игри – това, което ги прави увлекателни, не са само красивите графики, а начинът, по който всичко се движи и реагира на вашите действия. В момента вашата космическа игра е като красива картина, но ще добавим движение, което ще я вдъхне живот.
Когато инженерите на NASA програмираха компютъра за управление на мисията „Аполо“, те се сблъскаха със сходно предизвикателство: как да накарат космическия кораб да реагира на командите на пилота, докато автоматично поддържа корекции на курса? Принципите, които ще научим днес, отразяват тези същите концепции – управление на движение под контрол на играча заедно с автоматични системни поведения.
В този урок ще научите как да накарате космическите кораби да се плъзгат по екрана, да реагират на заповедите на играча и да създават плавни модели на движение. Ще разгледаме всичко на управляеми концепции, които естествено се изграждат една върху друга.
В края на урока ще можете да накарате играчите да управляват своя герой върху екрана, докато вражеските кораби патрулират над главите им. Още по-важно е, че ще разберете основните принципи, които движат системите за движение в игрите.
```mermaid
mindmap
root((Игра Анимация))
Movement Types
Player Controlled
Automatic Motion
Physics Based
Scripted Paths
Event Handling
Keyboard Input
Mouse Events
Touch Controls
Default Prevention
Game Loop
Update Logic
Render Frame
Clear Canvas
Frame Rate Control
Object Management
Position Updates
Collision Detection
Lifecycle Management
State Tracking
Communication
Pub/Sub Pattern
Event Emitters
Message Passing
Loose Coupling
```
## Предварителен тест преди лекцията
[Тест преди лекцията](https://ff-quizzes.netlify.app/web/quiz/33)
[Предварителен тест преди лекцията](https://ff-quizzes.netlify.app/web/quiz/33)
## Разбиране на движението в игрите
## Разбиране на игровото движение
Игрите оживяват, когато нещата започнат да се движат, и основно има два начина, по които това се случва:
Игрите оживяват, когато нещата започнат да се движат, и има основно два начина как това се случва:
- **Движение, контролирано от играча**: Когато натиснете клавиш или кликнете с мишката, нещо се движи. Това е директната връзка между вас и света на играта.
- **Автоматично движение**: Когато самата игра решава да движи нещата – например онези вражески кораби, които трябва да патрулират по екрана, независимо дали правите нещо или не.
- **Движение, контролирано от играча**: Когато натиснете клавиш или щракнете с мишката, нещо се движи. Това е директната връзка между вас и игровия свят.
- **Автоматично движение**: Когато самата игра решава да движи неща– като онези вражески кораби, които трябва да патрулират по екрана, независимо дали вие правите нещо или не.
Да накарате обекти да се движат на компютърен екран е по-лесно, отколкото си мислите. Спомняте ли си координатите x и y от часовете по математика? Точно с тях ще работим тук. Когато Галилей наблюдавал луните на Юпитер през 1610 г., той всъщност правел същото – проследявал позиции във времето, за да разбере моделите на движение.
Движението на обекти по компютърен екран е по-просто, отколкото може би мислите. Помните ли онези x и y координати от часовете по математика? Това е точно това, с което работим тук. Когато Галилео наблюдава луните на Юпитер през 1610 г., той всъщност правеше същото – чертаеше позиции във времето, за да разбере моделите на движение.
Движението на екрана е като създаване на анимация с листчета – трябва да следвате тези три прости стъпки:
Движението на екрана е като създаване на анимация от въртящи се картинки– трябва да следвате тези три прости стъпки:
1. **Актуализирайте позицията** – Променете къде трябва да бъде вашият обект (например преместете гос 5 пиксела надясно)
```mermaid
flowchart LR
A["Кадър N"] --> B["Обновяване на позициите"]
B --> C["Изчистване на платното"]
C --> D["Рисуване на обекти"]
D --> E["Кадър N+1"]
E --> F{Продължаваме?}
F -->|Да| B
F -->|Не| G["Край на играта"]
subgraph "Цикъл на анимацията"
H["1. Изчисляване на нови позиции"]
I["2. Изтриване на предишния кадър"]
J["3. Рендиране на новия кадър"]
end
style B fill:#e1f5fe
style C fill:#ffebee
style D fill:#e8f5e8
```
1. **Актуализирайте позицията** – Променете къде трябва да бъде обектът (може би го преместете 5 пиксела надясно)
2. **Изтрийте стария кадър** – Изчистете екрана, за да не виждате призрачни следи навсякъде
3. **Нарисувайте новия кадър** – Поставете обекта си на новото му място
3. **Начертайте новия кадър** – Поставете обекта си на новото място
Правете това достатъчно бързо и бум! Ще получите плавно движение, което се усеща естествено за играчите.
Направите ли го достатъчно бързо, и бац! Получавате плавно движение, което се усеща естествено за играчите.
Ето как може да изглежда това в код:
Ето как би могло да изглежда това в код:
```javascript
// Set the hero's location
// Задайте местоположението на героя
hero.x += 5;
// Clear the rectangle that hosts the hero
// Изчистете правоъгълника, в който се намира героят
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Redraw the game background and hero
// Прерисувайте фона на играта и героя
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "black";
ctx.drawImage(heroImg, hero.x, hero.y);
```
**Какво прави този код:**
**Ето какво прави този код:**
- **Актуализира** x-координатата на героя с 5 пиксела, за да го премести хоризонтално
- **Изчиства** цялата област на платното, за да премахне предишния кадър
- **Изчиства** цялата платно област, за да премахне предишния кадър
- **Запълва** платното с черен фон
- **Преначертава** изображението на героя на новата му позиция
- **Начертава отново** образа на героя на новата му позиция
✅ Можете ли да измислите причина, поради която преначертаването на героя много кадри в секунда може да доведе до разходи за производителност? Прочетете за [алтернативи на този модел](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Optimizing_canvas).
✅ Можете ли да помислите защо многократно изчертаване на героя много кадри в секунда може да повиши разходите за производителност? Прочетете за [алтернативите на този подход](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Optimizing_canvas).
## Обработка на събития от клавиатурата
## Обработване на събития от клавиатурата
Тук свързваме входа на играча с действията в играта. Когато някой натисне интервала, за да изстреля лазер, или докосне стрелка, за да избегне астероид, вашата игра трябва да открие и да реагира на този вход.
Тук свързваме входа от играча с действията в играта. Когато някой натисне интервала, за да стреля лазер, или докосне стрелка, за да избегне астероид, играта трябва да засече и реагира на този вход.
Събитията от клавиатурата сеслучват на ниво прозорец, което означава, че целият прозорец на браузъра слуша тези натискания на клавиши. Кликванията с мишката, от друга страна, могат да бъдат свързани със специфични елементи (като кликване върху бутон). За нашата космическа игра ще се фокусираме върху контроли с клавиатура, тъй като те дават на играчите класическо аркадно усещане.
Събитията от клавиатурата сеулавят на ниво прозорец, което означава, че целият ви браузър слуша тези натискания. Щракванията с мишката, от друга страна, могат да бъдат свързани с конкретни елементи (като натискане на бутон). За нашата космическа игра ще се фокусираме върху клавиатурните контроли, тъй като те дават онази класическа аркадна атмосфера.
Това ми напомня как телеграфните оператори през 1800-те години трябваше да превеждат входа на морзовия код в смислени съобщения – правим нещо подобно, превеждаме натисканията на клавиши в команди за игра.
Това ми напомня за операторите на телеграф в 1800-те години, които трябваше да превеждат морзов код в смислени съобщения – ние правим нещо подобно, превеждаме натискания на клавиши в игрални команди.
За да обработите събитие, трябва да използвате метода `addEventListener()` на прозореца и да му предоставите два входни параметъра. Първият параметър е името на събитието, например `keyup`. Вторият параметър е функцията, която трябва да бъде извикана в резултат на възникването на събитието.
За да обработите събитие, трябва да използвате метода `addEventListener()` на прозореца и да му подадете два входни параметъра. Първият е името на събитието, например `keyup`. Вторият е функцията, която трябва да се извика в резултат на настъпването на събитието.
Ето пример:
Ето един пример:
```javascript
window.addEventListener('keyup', (evt) => {
// evt.key = string representation of the key
// evt.key = низово представяне на клавиша
if (evt.key === 'ArrowUp') {
// do something
// направи нещо
}
});
```
**Разбивка на случващото се тук:**
- **Слуша** събития от клавиатурата в целия прозорец
- **Улавя** обекта на събитието, който съдържа информация за това кой клавиш е натиснат
- **Проверява** дали натиснатият клавиш съответства на конкретен клавиш (в случая стрелката нагоре)
- **Изпълнява** код, когато условието е изпълнено
**Разглобяване на това, което става тук:**
- **Слуша** за събития от клавиатурата върху целия прозорец
- **Улавя** обект на събитието, който съдържа информация за това кой клавиш е натиснат
- **Проверява** дали натиснатият клавиш съвпада с конкретен (в този случай стрелка нагоре)
- **Изпълнява** код, когато условието е истинско
Засъбития от клавиатурата има два свойства на събитието, които можете да използвате, за да видите кой клавиш е натиснат:
Заключови събития има две свойства в обекта на събитието, които можете да използвате, за да видите кой клавиш е натиснат:
- `key` - това етекстово представяне на натиснатия клавиш, например `'ArrowUp'`
- `key` - това енизово представяне на натиснатия клавиш, например `'ArrowUp'`
- `keyCode` - това е числово представяне, например `37`, което съответства на `ArrowLeft`
✅ Манипулацията на събития от клавиатурата е полезна извън разработката на игри. За какви други приложения можете да се сетите за тази техника?
✅ Манипулирането на ключови събития е полезно и извън разработването на игри. За какви други приложения се сещате за тази техника?
### Специални клавиши: внимание!
```mermaid
sequenceDiagram
participant User
participant Browser
participant EventSystem
participant GameLogic
participant Hero
User->>Browser: Натиска клавиша ArrowUp
Browser->>EventSystem: keydown събитие
EventSystem->>EventSystem: preventDefault()
EventSystem->>GameLogic: emit('KEY_EVENT_UP')
GameLogic->>Hero: hero.y -= 5
Hero->>Hero: Актуализира позицията
Note over Browser,GameLogic: Потокът на събития предотвратява подразбиранията на браузъра
Note over GameLogic,Hero: Pub/sub моделът осигурява чиста комуникация
```
### Специални клавиши: предупреждение!
Някои клавиши имат вградени поведения на браузъра, които могат да попречат на вашата игра. Стрелките превъртат страницата, а интервалът я премества надолу – поведения, които не искате, когато някой се опитва да управлява своя космически кораб.
Някои клавиши имат вградени браузърни поведения, които могат да се намесят в играта ви. Стрелките превъртат страницата и интервалът прескача надолу – поведения, които не искате, когато някой се опитва да управлява космическия си кораб.
Можем да предотвратим тези стандартни поведения и да оставим нашата игра да обработва входа вместо това. Това е подобно на начина, по който ранните компютърни програмисти трябваше да отменят системни прекъсвания, за да създадат персонализирани поведения – просто го правим на ниво браузър. Ето как:
Можем да предотвратим тези стандартни поведения и да оставим играта да се справи с входа вместо това. Това е подобно на начина, по който ранните програмисти на компютри са трябвало да отменят системни прекъсвания, за да създадат собствени поведения – просто го правим на ниво браузър. Ето как:
```javascript
const onKeyDown = function (e) {
@ -106,12 +189,12 @@ const onKeyDown = function (e) {
- ✅ Опишете как слушателите на събития свързват потребителския вход с логиката на играта
- ✅ Идентифицирате кои клавиши може да се намесят в управлението на играта
**Бърз само тест**: Какво би станало, ако не предотвратите стандартното поведение за стрелките?
*Отговор: Браузърът ще превърта страницата, което пречи на движението в играта*
**Архитектура на системата за събития**: Вече разбирате:
- **Слушане на ниво прозорец**: Засичане на събития на ниво браузър
- **Свойства на обекта събитие**: низове `key` спрямо числа `keyCode`
- **Предотвратяване на действие по подразбиране**: Спиране на нежелани браузърни поведения
- **Условна логика**: Реакция на конкретни комбинации от клавиши
## Движение, предизвикано от играта
Сега нека поговорим за обекти, които се движат без вход от играча. Помислете за вражески кораби, които се движат по екрана, куршуми, летящи в прави линии, или облаци, които се носят на заден план. Това автономно движение прави света на играта да изглежда жив, дори когато никой не докосва контролите.
Сега нека говорим за обекти, които се движат без вход от играча. Помислете за вражески кораби, които кръстосват екрана, куршуми, летящи в прави линии, или облаци, носени на заден план. Това автономно движение прави света на играта да изглежда жив, дори когато никой не докосва контролите.
Използваме вградените таймери на JavaScript, за да актуализираме позициите на редовни интервали. Тази концепция е подобна на начина, по който работят махаловите часовници – редовен механизъм, който задейства последователни, времеви действия. Ето колко просто може да бъде:
Използваме вградените таймери на JavaScript, за да актуализираме позициите на редовни интервали. Този концепт е подобен на начина, по който работят махаловите часовници – редовен механизъм, който задейства последователни, времево контролирани действия. Ето колко просто може да бъде:
```javascript
const id = setInterval(() => {
// Move the enemy on the y axis
// Преместете врага по оста y
enemy.y += 10;
}, 100);
```
**Какво прави този код за движение:**
**Ето какво прави този код за движение:**
- **Създава** таймер, който се изпълнява на всеки 100 милисекунди
- **Актуализира** y-координатата на врага с 10 пиксела всеки път
- **Съхранява** ID на интервала, за да можем да го спрем по-късно, ако е необходимо
- **Премества** врага надолу по екрана автоматично
- **Съхранява** ID на интервала, за да можем да го спрем по-късно при нужда
- **Движи** врага надолу по екрана автоматично
## Игровият цикъл
Ето концепцията, която обединява всичко– игровият цикъл. Ако вашата игра беше филм, игровият цикъл щеше да бъде проекторът, показващ кадър след кадър толкова бързо, че всичко изглежда плавно.
Ето концепцията, която свързва всичко заедно– игровият цикъл. Ако вашата игра беше филм, игровият цикъл щеше да бъде прожекционният апарат, който показва кадър след кадър толкова бързо, че всичко изглежда да се движи плавно.
Всяка игра има един от тези цикли, който работи зад кулисите. Това е функция, която актуализира всички игрови обекти, преначертава екрана и повтаря този процес непрекъснато. Това следи вашия герой, всички врагове, всички летящи лазери – цялото състояние на играта.
Всяка игра има един такъв цикъл, работещ зад кулисите. Това е функция, която актуализира всички игрови обекти, прерисува екрана и повтаря този процес непрекъснато. Тя следи героя ви, всички врагове, всички лазери, които летят наоколо – цялото игрово състояние.
Тази концепция ми напомня как ранните аниматори като Уолт Дисни трябваше да преначертават героите кадър по кадър, за да създадат илюзията за движение. Ние правим същото, само чес код вместо с моливи.
Тази концепция ми напомня как ранните аниматори във филмовата индустрия, като Уолт Дисни, са рисували героите кадър по кадър, за да създадат илюзията на движение. Ние правим същото, нос код вместо с моливи.
Ето как обикновено изглежда игровият цикъл, изразен в код:
Ето как един игров цикъл типично може да изглежда в код:
```mermaid
flowchart TD
A["Стартиране на игровия цикъл"] --> B["Изчистване на канваса"]
- **Изчиства** цялото платно, за да премахне предишния кадър
- **Запълва** фона с плътен цвят
- **Рисува** всички игрови обекти на текущите им позиции
- **Запълва** фона с плътно блока
- **Начертава** всички игрови обекти на текущите им позиции
- **Повтаря** този процес на всеки 200 милисекунди, за да създаде плавна анимация
- **Управлява** честотата на кадрите чрез контролиране на времето на интервала
- **Управлява** честотата на кадрите чрез контрол на времето за интервала
## Продължаване на космическата игра
Сега ще добавим движение към статичната сцена, която създадохте преди. Ще я трансформираме от екранна снимка в интерактивно изживяване. Ще работим стъпка по стъпка, за да гарантираме, че всяка част се надгражда върху предишната.
Сега ще добавим движение към статичната сцена, която изградихте по-рано. Ще я трансформираме от снимка в интерактивно преживяване. Ще работим стъпка по стъпка, за да сме сигурни, че всяка част се гради върху предишната.
Вземете кода от мястото, където спряхме в предишния урок (или започнете с кода в папката [Part II- starter](../../../../6-space-game/3-moving-elements-around/your-work), ако имате нужда от ново начало).
Вземете кода от мястото, на което спряхме в предишния урок (или започнете от кода в папката [Part II- starter](../../../../6-space-game/3-moving-elements-around/your-work), ако искате ново начало).
**Ето какво ще изградим днес:**
- **Контроли на героя**: Стрелките ще управляват вашия космически кораб по екрана
- **Движение на враговете**: Тези извънземни кораби ще започнат своето настъпление
- **Контроли на героя**: стрелките ще управляват космическия кораб из екрана
- **Движение на враговете**: онези извънземни кораби ще започнат настъпление
Започнете проекта си в папката `your-work`, като въведете:
Започвате проекта си в папката `your-work`, като напишете:
```bash
cd your-work
@ -209,17 +332,17 @@ npm start
**Какво прави тази команда:**
- **Навигира** до директорията на вашия проект
- **Стартира** HTTP сървър на адрес `http://localhost:5000`
- **Сервира** файловете на вашата игра, за да можете да ги тествате в браузър
- **Сервира** вашите файлове с играта, за да можете да ги тествате в браузър
Горната команда ще стартира HTTP сървър на адрес `http://localhost:5000`. Отворете браузър и въведете този адрес, в момента трябва да се визуализира героят и всички врагове; нищо все още не се движи - но скоро ще!
Горната команда ще стартира HTTP сървър на адрес `http://localhost:5000`. Отворете браузър и въведете този адрес, в момента би трябвало да видите героя и всички врагове; нищо още не се движи!
### Добавяне на код
### Добавете код
1. **Добавете специални обекти** за `hero`, `enemy` и `game object`, те трябва да имат свойства `x` и `y`. (Спомнете си частта за [Наследяване или композиция](../README.md)).
1. **Добавете специализирани обекти** за `hero`, `enemy` и `game object`, те трябва да имат свойства `x` и `y`. (Помнете частта за [наследяване или композиция](../README.md)).
*ПОДСКАЗКА* `game object` трябва да бъде този с`x` и `y` и способността да се рисува върху платно.
*СЪВЕТ* `game object` трябва да е този, който има `x` и `y` и способността да се рисува на платното.
> **Съвет**: Започнете, като добавите нов клас `GameObject`с неговия конструктор, описан по-долу, и след това го нарисувайте върху платното:
> **Подсказка**: Започнете с добавяне на нов клас `GameObject`с конструктора, описан по-долу, и след това го нарисувайте на платното:
```javascript
class GameObject {
@ -240,12 +363,48 @@ npm start
```
**Разбиране на този базов клас:**
- **Определя** общи свойства, които всички игрови обекти споделят (позиция, размер, изображение)
- **Дефинира** общи свойства, които всички игрови обекти споделят (положение, размер, изображение)
- **Включва** флаг `dead`, за да следи дали обектът трябва да бъде премахнат
- **Осигурява** метод `draw()`, който изобразява обекта върху платното
- **Задава** стандартни стойности за всички свойства, които дъщерните класове могат да заменят
- **Осигурява** метод `draw()`, който рисува обекта на платното
- **Задава** стойности по подразбиране за всички свойства, които дочерните класове могат да пренапишат
Сега разширете този `GameObject`, за да създадете `Hero` и `Enemy`:
```mermaid
classDiagram
class GameObject {
+x: number
+y: number
+dead: boolean
+type: string
+width: number
+height: number
+img: Image
+draw(ctx)
}
class Hero {
+speed: number
+type: "Герой"
+width: 98
+height: 75
}
class Enemy {
+type: "Враг"
+width: 98
+height: 50
+setInterval()
}
GameObject <|-- Hero
GameObject <|-- Enemy
class EventEmitter {
+listeners: object
+on(message, listener)
+emit(message, payload)
}
```
Сега, разширете този `GameObject`, за да създадете `Hero` и `Enemy`:
```javascript
class Hero extends GameObject {
@ -278,53 +437,53 @@ npm start
}
```
**Основни концепции в тези класове:**
- **Наследява** от `GameObject`, използвайки ключовата дума `extends`
- **Извиква** конструктора на родителя с`super(x, y)`
- **Задава** специфични размери и свойства за всеки тип обект
- **Имплементира** автоматично движение за враговете, използвайки`setInterval()`
**Ключови концепции в тези класове:**
- **Наследяват** от `GameObject` чрез ключовата дума `extends`
- **Извикват** конструктора на родителя с`super(x, y)`
- **Задават** специфични размери и свойства за всеки тип обект
- **Реализират** автоматично движение за враговете чрез`setInterval()`
2. **Добавете обработчици на събития от клавиатурата**, за да управлявате движението на героя (нагоре/надолу, наляво/надясно)
2. **Добавете обработващи функции за събития от клавиатурата**, за да навигирате с клавишите (местене на героя нагоре/надолу, наляво/надясно)
*ЗАПОМНЕТЕ* това е картезианска система, горният ляв ъгъл е`0,0`. Също така не забравяйте да добавите код за спиране на *стандартното поведение*
*ПОМНЕТЕ* това е декартова система, горе вляво е`0,0`. Също не забравяйте да добавите код за предотвратяване на *стандартното поведение*
> **Съвет**: Създайте вашата функция `onKeyDown` и я свържете към прозореца:
> **Подсказка**: Създайте функцията `onKeyDown` и я прикрепете към прозореца:
```javascript
const onKeyDown = function (e) {
console.log(e.keyCode);
// Add the code from the lesson above to stop default behavior
// Добавете кода от урока по-горе, за да спрете подразбираното поведение
switch (e.keyCode) {
case 37:
case 39:
case 38:
case 40: // Arrow keys
case 40: // Стрелки на клавиатурата
case 32:
e.preventDefault();
break; // Space
break; // Интервал
default:
break; // do not block other keys
break; // не блокирайте други клавиши
}
};
window.addEventListener("keydown", onKeyDown);
```
**Какво прави този обработчик на събития:**
- **Слуша** събития за натискане на клавиши в целия прозорец
- **Записва** кода на клавиша, за да ви помогне да разберете кои клавиши се натискат
**Какво прави този обработчик на събитието:**
- **Слуша** за събития `keydown` върху целия прозорец
- **Логва** кода на клавиша, за да ви помогне да отстраните проблеми кои клавиши са натиснати
- **Предотвратява** стандартното поведение на браузъра за стрелките и интервала
- **Позволява** други клавиши да функционират нормално
- **Позволява** на другите клавиши да функционират нормално
Проверете конзолата на браузъра си на този етап и наблюдавайте как се записват натисканията на клавиши.
Проверете конзолата на браузъра си в този момент и наблюдавайте регистрираните натискания на клавиши.
3. **Имплементирайте** [Модела Pub-Sub](../README.md), това ще поддържа кода ви чист, докато следвате останалите части.
3. **Реализирайте** [патърна Pub sub](../README.md), това ще държи кода ви чист, докато следвате останалите части.
Моделът Publish-Subscribe помага да организирате кода си, като разделя откриването на събития от тяхната обработка. Това прави кода ви по-модулен и лесен за поддръжка.
Патърнът Publish-Subscribe помага да организирате кода си, като разделя засичането на събития от обработването им. Това прави кода ви по-модулен и по-лесен за поддръжка.
Зада направите тази последна част, можете:
За последната част можете да:
1. **Добавете слушател на събития** към прозореца:
1. **Добавите слушател за събития** на прозореца:
```javascript
window.addEventListener("keyup", (evt) => {
@ -341,12 +500,33 @@ npm start
```
**Какво прави тази система за събития:**
- **Открива** вход от клавиатурата и го преобразува в персонализирани събития за игра
- **Разделя** откриването на вход от логиката на играта
- **Прави** лесно промяната на контролите по-късно, без да се засяга кода на играта
- **Позволява** множество системи да реагират на един и същ вход
2. **Създайте клас EventEmitter**, за да публикувате и абонирате съобщения:
- **Разпознава** вход от клавиатура и го превръща в персонализирани игрови събития
- **Разделя** откриването на входа от игровата логика
- **Позволява** лесна промяна на контролите без да се засяга игралният код
- **Позволява** на множество системи да реагират на един и същи вход
```mermaid
flowchart TD
A["Въвеждане от клавиатура"] --> B["Слушател за събития на прозореца"]
B --> C["Излъчвател на събития"]
C --> D["KEY_EVENT_UP"]
C --> E["KEY_EVENT_DOWN"]
C --> F["KEY_EVENT_LEFT"]
C --> G["KEY_EVENT_RIGHT"]
D --> H["Движение на героя"]
D --> I["Звукова система"]
D --> J["Визуални ефекти"]
E --> H
F --> H
G --> H
style A fill:#e1f5fe
style C fill:#e8f5e8
style H fill:#fff3e0
```
2. **Създайте клас EventEmitter**, за да публикувате и абонирате за съобщения:
```javascript
class EventEmitter {
@ -361,6 +541,7 @@ npm start
this.listeners[message].push(listener);
}
3. **Добавете константи** и настройте EventEmitter:
```javascript
@ -381,14 +562,89 @@ npm start
```
**Разбиране на настройката:**
- **Определя** константи за съобщения, за да избегне грешки и да улесни рефакторинга
- **Декларира** променливи за изображения, контекст на плат
- **Създава** мрежа от врагове, използвайки вложени цикли
- **Присвоява** изображението на врага на всеки обект враг
- **Добавя** всеки враг към глобалния масив с игрови обекти
- **Дефинира** константи за съобщения, за да се избегнат правописни грешки и да улесни промяната на кода
- **Декларира** променливи за изображения, контекст на платното и състоянието на играта
- **Създава** глобален емитент на събития за системата pub-sub
- **Инициализира** масив за съхранение на всички игрови обекти
4. **Инициализирайте играта**
```javascript
function initGame() {
gameObjects = [];
createEnemies();
createHero();
eventEmitter.on(Messages.KEY_EVENT_UP, () => {
hero.y -= 5;
});
eventEmitter.on(Messages.KEY_EVENT_DOWN, () => {
hero.y += 5;
});
eventEmitter.on(Messages.KEY_EVENT_LEFT, () => {
hero.x -= 5;
});
4. **Настройка на игровия цикъл**
Преработете функцията `window.onload`, за да инициализирате играта и да създадете игров цикъл с подходящ интервал. Също така ще добавите лазерен лъч:
- **Изчислява** позиции за центриране на враговете на екрана
- **Създава** мрежа от врагове с вложени цикли
- **Присвоява** образа на врага на всеки враг обект
- **Добавя** всеки враг към глобалния масив с игрови обекти
и добавете функция `createHero()`, която прави подобен процес за героя.
```javascript
function createHero() {
hero = new Hero(
@ -399,28 +655,48 @@ npm start
gameObjects.push(hero);
}
```
**Какво прави създаването на героя:**
- **Позиционира** героя в долния център на екрана
- **Присвоява** изображението на героя на обекта герой
- **Добавя** героя към масива с игрови обекти за рендиране
и накрая добавете функция `drawGameObjects()`, за да започнете рисуването:
**Какво прави създаването на героя:**
- **Поставя** героя в долния център на екрана
- **Присвоява** образа на героя към героя обект
- **Добавя** героя в масива с игрови обекти за рендиране
и накрая, добавете функция `drawGameObjects()`, за да започнете рисуването:
```javascript
function drawGameObjects(ctx) {
gameObjects.forEach(go => go.draw(ctx));
}
```
**Разбиране на функцията за рисуване:**
- **Итерира** през всички игрови обекти в масива
- **Извиква** метода `draw()` за всеки обект
- **Предава** контекста на платното, за да могат обектите да се рендират сами
Вашите врагове трябва да започнат да настъпват към космическия кораб на героя!
}
}
**Разбиране на функцията за рисуване:**
- **Итерира** през всички игрови обекти в масива
- **Извиква** метода `draw()` на всеки обект
- **Подава** контекста на canvas, за да могат обектите да се визуализират
### 🔄 **Педагогически преглед**
**Пълно разбиране на игровата система**: Проверкете майсторството си върху цялата архитектура:
- ✅ Как наследяването позволява на Hero и Enemy да споделят общи свойства на GameObject?
- ✅ Защо pub/sub моделът прави кода ви по-поддържаем?
- ✅ Каква роля играе игровият цикъл за създаване на плавна анимация?
- ✅ Как слушателите на събития свързват потребителския вход с поведението на игровите обекти?
**Интеграция на системата**: Вашата игра вече демонстрира:
- **Обектно-ориентиран дизайн**: Базови класове с специализирано наследяване
- **Архитектура, базирана на събития**: Pub/sub модел за слаба свързаност
- **Анимационна рамка**: Игров цикъл с консистентни обновявания на кадрите
- **Обработка на вход**: Събития от клавиатура с предпазване от подразбиращи се действия
- **Управление на ресурси**: Зареждане на изображения и рендиране на спрайтове
**Професионални модели**: Прилагали сте:
- **Разделяне на отговорностите**: Отделни логики за вход, логика и рендериране
- **Полиморфизъм**: Всички игрови обекти споделят общ интерфейс за рисуване
- **Предаване на съобщения**: Чиста комуникация между компонентите
- **Управление на ресурси**: Ефективно боравене със спрайтове и анимации
Вашите врагове трябва да започнат да настъпват към вашия герой на космическия кораб!
}
}
```
and add a `createHero()` function to do a similar process for the hero.
@ -435,68 +711,190 @@ npm start
gameObjects.push(hero);
}
```
и накрая добавете функция `drawGameObjects()`, за да започнете рисуването:
и накрая, добавете функция `drawGameObjects()`, за да започнете рисуването:
```javascript
function drawGameObjects(ctx) {
gameObjects.forEach(go => go.draw(ctx));
}
```
Вашите врагове трябва да започнат да настъпват към космическия кораб на героя!
Вашите врагове трябва да започнат да настъпват към вашия герой на космическия кораб!
---
## Предизвикателство на GitHub Copilot Agent 🚀
## GitHub Copilot Agent Challenge 🚀
Ето едно предизвикателство, което ще подобри полировката на вашата игра: добавяне на граници и плавни контроли. В момента вашият герой може да излети извън екрана, а движението може да изглежда накъсано.
Ето едно предизвикателство, което ще подобри изглаждането на вашата игра: добавяне на граници и плавен контрол. В момента вашият герой може да излезе извън екрана, а движението може да е на прекъснати стъпки.
**Вашата мисия:** Направете космическия кораб да се усеща по-реалистично, като внедрите граници на екрана и плавно движение. Това е подобно на начина, по който системите за управление на полети на НАСА предотвратяват превишаването на безопасните оперативни параметри на космическите кораби.
**Вашата мисия:** Направете вашия космически кораб по-реалистичен, като добавите граници на екрана и плавно движение. Това е подобно на начина, по който NASA използва системи за управление на полетите, за да предотврати излизане на космически кораби извън безопасните експлоатационни параметри.
**Какво да изградите:** Създайте система, която да задържа космическия кораб на героя на екрана и направете контролите да се усещат плавно. Когато играчите задържат клавиш със стрелка, корабът трябва да се движи плавно, вместо да се премества на отделни стъпки. Помислете за добавяне на визуална обратна връзка, когато корабът достигне границите на екрана – например лек ефект, който да показва края на игровата зона.
**Ето какво да изградите:** Създайте система, която държи героя ви на екрана и направете контролите плавни. Когато играчите задържат стрелка, корабът плавно да се движи непрекъснато, вместо да се мести на отделни стъпки. Помислете за добавяне на визуална обратна връзка, когато корабът достигне границите на екрана – например лек ефект за индикиране края на игровата зона.
Научете повече за [режим агент](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
Научете повече за [agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
## 🚀 Предизвикателство
## 🚀 Предизвикателство
Организацията на кода става все по-важна, когато проектите растат. Може би сте забелязали, че вашият файл става претрупан с функции, променливи и класове, смесени заедно. Това ми напомня за начина, по който инженерите, организиращи кода за мисията Аполо, трябваше да създадат ясни, поддържани системи, върху които множество екипи да могат да работят едновременно.
Организацията на кода става все по-важнас нарастване на проектите. Може би сте забелязали, че файлът ви се запълва с функции, променливи и класове, преплетени заедно. Това ми напомня как инженерите, организиращи кода за мисия Apollo, са създавали ясни и поддържими системи, върху които са работели няколко екипа едновременно.
**Вашата мисия:**
Мислете като софтуерен архитект. Как бихте организирали кода си така, че след шест месеца вие (или ваш колега) да можете да разберете какво се случва? Дори всичко да остане в един файл засега, можете да създадете по-добра организация:
**Вашата мисия:**
Мислете като софтуерен архитект. Как бихте организирали кода си така, че след шест месеца вие (или колега) да можете да разберете какво се случва? Дори и всичко да остане в един файл засега, можете да създадете по-добра организация:
- **Групиране на свързани функции** заедно с ясни заглавия на коментари
- **Разделяне на отговорностите** - отделете игровата логика от рендирането
- **Използване на последователни наименования** за променливи и функции
- **Създаване на модули** или пространства от имена за организиране на различни аспекти на вашата игра
- **Добавяне на документация**, която обяснява целта на всяка основна секция
- **Групиране на свързани функции** заедно с ясни заглавни коментари
- **Разделяне на отговорности** – отделяйте логиката на играта от рендерирането
- **Използване на последователни имена** за променливи и функции
- **Създаване на модули** или namespaces за организация на различни аспекти от играта
- **Добавяне на документация**, която обяснява целта на всяка голяма секция
**Въпроси за размисъл:**
- Кои части от вашия код са най-трудни за разбиране, когато се върнете към тях?
- Как бихте могли да организирате кода си, за да улесните някой друг да допринесе?
- Какво би се случило, ако искате да добавите нови функции като бонуси или различни типове врагове?
**Въпроси за размисъл:**
- Кои части от кода виса най-трудни за разбиране, когато се върнете към тях?
- Как бихте организирали кода си, за да е по-лесно на друг да допринася?
- Какво би станало, ако искате да добавите нови функции като power-ups или различни видове врагове?
## Тест след лекцията
## Следлекционен тест
[Тест след лекцията](https://ff-quizzes.netlify.app/web/quiz/34)
Създаваме всичко от нулата, което е страхотно за учене, но ето една малка тайна – има невероятни JavaScript рамки, които могат да се справят с много от тежката работа вместо вас. След като се почувствате уверени с основите, които разгледахме, си струва [да проучите наличните опции](https://github.com/collections/javascript-game-engines).
Ние изграждаме всичко от нулата, което е фантастично за учене, но ето една малка тайна – съществуват страхотни JavaScript фреймуъркове, които могат да поемат голяма част от тежката работа вместо вас. След като се почувствате комфортно с основите, които покрихме, си струва да [проучите какво има](https://github.com/collections/javascript-game-engines).
Мислете за рамките като за добре оборудвана кутия с инструменти, вместо да правите всеки инструмент на ръка. Те могат да решат много от тези предизвикателства за организация на кода, за които говорихме, плюс да предложат функции, които биха отнели седмици за изграждане сами.
Помислете за фреймуърковете като за добре зареден инструментариум, вместо да правите всеки инструмент на ръка. Те могат да решат много от проблемите с организацията на кода, които обсъждахме, както и да предоставят функции, които биха отнели седмици да изградите сами.
**Неща, които си струва да се проучат:**
- Как игровите двигатели организират кода – ще бъдете изумени от умните модели, които използват
- Трикове за производителност, които правят игрите с платно да работят гладко
- Съвременни функции на JavaScript, които могат да направят кода ви по-чист и по-лесен за поддръжка
- Различни подходи за управление на игрови обекти и техните взаимоотношения
**Неща, които си струва да проучите:**
- Как гейм енджините организират кода – ще се изненадате от умните модели, които използват
- Трикове за производителност, които правят canvas игрите наистина плавни
- Модерни JavaScript възможности, които правят кода по-чист и по-лесен за поддръжка
- Различни подходи за управление на игрови обекти и техните взаимоотношения
## Задача
## 🎯 Вашата времева линия за овладяване на играна анимация
[Коментирайте вашия код](assignment.md)
```mermaid
timeline
title Напредък в обучението по анимация и взаимодействие в игри
section Основи на движението (20 минути)
Принципи на анимацията: Анимация на кадри
: Актуализации на позицията
: Координатни системи
: Плавно движение
section Системи за събития (25 минути)
Въвеждане от потребителя: Обработка на събития от клавиатура
: Предотвратяване на подразбиращо се поведение
: Свойства на обекта събитие
: Слушане на ниво прозорец
section Архитектура на играта (30 минути)
Дизайн на обекти: Модели на наследяване
: Създаване на базов клас
: Специализирани поведения
: Полиморфни интерфейси
section Шаблони за комуникация (35 минути)
Реализация Pub/Sub: Излъчватели на събития
: Константи на съобщения
: Свободно свързване
: Интеграция на системи
section Майсторство в игровия цикъл (40 минути)
Системи в реално време: Контрол на честотата на кадрите
: Цикъл обновяване/изобразяване
: Управление на състоянието
: Оптимизация на производителността
section Разширени техники (45 минути)
Професионални функции: Откриване на сблъсъци
: Физическа симулация
: Машини на състояния
: Компонентни системи
section Концепции на игрови двигатели (1 седмица)
Разбиране на рамкова структура: Системи съставени от същности и компоненти
: Графи на сцени
: Поток на активи
: Профилиране на производителността
section Производствени умения (1 месец)
Професионално развитие: Организация на кода
: Екипно сътрудничество
: Стратегии за тестване
: Оптимизация на разгръщането
```
### 🛠️ Обобщение на вашия набор от инструменти за разработка на игри
След завършване на този урок вече сте овладели:
- **Принципи на анимацията**: движение на база на кадри и плавни преходи
- **Програмиране, базирано на събития**: Обработка на клавишен вход с правилно управление на събитията
- **Обектно-ориентиран дизайн**: Наследствени йерархии и полиморфни интерфейси
- **Комуникационни модели**: Pub/sub архитектура за поддържам код
- **Архитектура на игровия цикъл**: Цикли за обновяване и рендериране в реално време
- **Системи за въвеждане**: Картографиране на управление с предпазване от подразбирани действия
- **Управление на ресурси**: Зареждане на спрайтове и ефективни техники за рендериране
### ⚡ **Какво можете да направите в следващите 5 минути**
- [ ] Отворете конзолата в браузъра и пробвайте `addEventListener('keydown', console.log)`, за да видите клавишните събития
- [ ] Създайте прост div елемент и го движете с стрелки на клавиатурата
- [ ] Експериментирайте с`setInterval` за създаване на непрекъснато движение
- [ ] Опитайте да спрете подразбираното поведение с`event.preventDefault()`
### 🎯 **Какво можете да постигнете този час**
- [ ] Попълнете следлекционния тест и разберете програмирането, базирано на събития
- [ ] Създайте подвижния герой космически кораб с пълно управление на клавиатурата
- [ ] Прилагайте плавни модели на движение за враговете
- [ ] Добавете граници, за да предотвратите напускането на игровите обекти от екрана
- [ ] Създайте базово засичане на сблъсъци между игрови обекти
### 📅 **Вашето седмично пътешествие в анимацията**
- [ ] Завършете пълната космическа игра с полиран контрол на движението и взаимодействия
- [ ] Добавете сложни модели на движение като криви, ускорение и физика
- [ ] Прилагайте плавни преходи и easing функции
- [ ] Създавайте частици и системи за визуална обратна връзка
- [ ] Оптимизирайте производителността за плавна игра с 60fps
- [ ] Добавете мобилни тъч контроли и адаптивен дизайн
### 🌟 **Вашето месечно интерактивно развитие**
- [ ] Изградете сложни интерактивни приложения с усъвършенствани анимационни системи
- [ ] Научете анимационни библиотеки като GSAP или създайте собствен анимационен движок
- [ ] Допринасяйте за open source проекти за игри и анимация
- [ ] Овладейте оптимизацията на производителността за графично интензивни приложения
- [ ] Създавайте образователно съдържание за игродизайн и анимация
**Приложения в реалния свят**: Вашите умения за анимация в игрите се прилагат директно към:
- **Интерактивни уеб приложения**: Динамични табла и интерфейси в реално време
- **Визуализация на данни**: Анимирани графики и интерактивни визуализации
- **Образователен софтуер**: Интерактивни симулации и обучителни инструменти
- **Мобилна разработка**: Игри с тъч управление и жестове
- **Десктоп приложения**: Electron приложения с плавни анимации
- **Уеб анимации**: Библиотеки за анимации с CSS и JavaScript
**Професионални умения, които сте придобили**: Можете сега да:
- **Проектирате** системи, базирани на събития, които се разрастват според сложността
- **Прилагате** плавни анимации с математически принципи
- **Отстранявате грешки** в сложни системи за взаимодействие с помощта на браузърни инструменти за разработчици
- **Оптимизирате** производителността на игрите за различни устройства и браузъри
- **Дизайнирате** поддържащ се код с доказани модели
**Придобити концепции в игродизайна**:
- **Управление на честота на кадрите**: Разбиране на FPS и контрол на времето
- **Обработка на вход**: Кросплатформени клавиатурни и събитийни системи
- **Животен цикъл на обектите**: Модели за създаване, обновяване и унищожаване
- **Синхронизация на състоянието**: Поддържане на консистентност на игровото състояние между кадрите
- **Архитектура на събития**: Свързана комуникация между игрови системи
**Следващо ниво**: Вие сте готови да добавите засичане на сблъсъци, системи за точкуване, звукови ефекти или да изследвате модерни игрови фреймуъркове като Phaser или Three.js!
🌟 **Постигнато постижение**: Изградихте пълна интерактивна игрова система с професионални архитектурни модели!
## Задача
[Коментирайте кода си](assignment.md)
---
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Отказ от отговорност**:
Този документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод.
Този документ е преведен с помощта на AI преводаческа услуга [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, имайте предвид, че автоматичните преводи могат да съдържат грешки или неточности. Оригиналният документ на неговия първоначален език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за никакви недоразумения или неправилни тълкувания, възникнали в резултат на използването на този превод.
Помислете за момента в "Междузвездни войни", когато протонните торпеда на Люк попаднаха в отдушника на Звездата на смъртта. Точно това откриване на сблъсък промени съдбата на галактиката! В игрите откриването на сблъсъци работи по същия начин - определя кога обектите взаимодействат и какво се случва след това.
В този урок ще добавите лазерни оръжия към вашата космическа игра и ще внедрите система за откриване на сблъсъци. Точно както плановиците на мисии в НАСА изчисляват траекториите на космическите кораби, за да избегнат отломки, вие ще научите как да откривате пресичания на игрови обекти. Ще разделим това на управляеми стъпки, които се надграждат една върху друга.
До края ще имате функционираща бойна система, в която лазерите унищожават враговете, а сблъсъците задействат игрови събития. Тези принципи за откриване на сблъсъци се използват във всичко - от симулации на физика до интерактивни уеб интерфейси.
✅ Направете малко проучване за първата компютърна игра, която някога е била написана. Каква беше нейната функционалност?
# Създаване на Космическа Игра Част 4: Добавяне на Лазер и Откриване на Сблъсъци
```mermaid
journey
title Вашето пътуване в откриването на сблъсъци
section Физическа основа
Разберете правоъгълници: 3: Student
Научете се на интерсекционна математика: 4: Student
Помислете за момента от Междузвездни войни, когато протонните торпеда на Люк удрят изпускателния отвор на Звездата на смъртта. Точно това откриване на сблъсък промени съдбата на галактиката! В игрите, откриването на сблъсъци работи по същия начин - то определя кога обектите взаимодействат и какво се случва след това.
В този урок ще добавите лазерно оръжие към вашата космическа игра и ще имплементирате откриване на сблъсъци. Точно както плановете на НАСА изчисляват траекториите на космическите кораби, за да избегнат отломки, така и вие ще научите как да откривате кога обектите в играта се пресичат. Ще разделим това на управляеми стъпки, които се изграждат една върху друга.
В края ще имате функционираща бойна система, където лазерите унищожават враговете, а сблъсъците задействат игрови събития. Същите принципи за откриване на сблъсъци се използват във всичко от физически симулации до интерактивни уеб интерфейси.
```mermaid
mindmap
root((Откриване на сблъсъци))
Physics Concepts
Граници на правоъгълник
Тестове за пресичане
Координатни системи
Логика на разделяне
Game Objects
Лазерни снаряди
Вражески кораби
Главен герой
Зони на сблъсък
Lifecycle Management
Създаване на обекти
Обновяване на движение
Маркиране за унищожаване
Почистване на паметта
Event Systems
Въвеждане от клавиатура
Събития при сблъсък
Промени в състоянието на играта
Аудио/Визуални ефекти
Performance
Ефективни алгоритми
Оптимизация на кадровата честота
Управление на паметта
Пространствено разделяне
```
✅ Направете малко проучване за първата компютърна игра някога написвана. Каква беше нейната функционалност?
## Откриване на сблъсъци
Откриването на сблъсъци работи като сензорите за близост на лунния модул "Аполо" - постоянно проверява разстоянията и задейства предупреждения, когато обектите се приближат твърде много. В игрите тази система определя кога обектите взаимодействат и какво трябва да се случи след това.
Откриването на сблъсъци работи като датчиците за близост на лунния модул Apollo - постоянно проверява разстоянията и задейства аларми, когато обектите се доближат прекалено много. В игрите тази система определя кога обектите взаимодействат и какво трябва да се случи след това.
Подходът, който ще използваме, третира всеки игрови обект като правоъгълник, подобно на начина, по който системите за контрол на въздушния трафик използват опростени геометрични форми за проследяване на самолети. Този метод с правоъгълници може да изглежда прост, но е изчислително ефективен и работи добре за повечето игрови сценарии.
Подходът, който ще използваме, третира всеки игрови обект като правоъгълник, подобно на начина, по който системите за контрол на въздушното движение използват опростени геометрични форми за проследяване на самолети. Този правоъгълен метод може да изглежда прост, но е изчислително ефективен и работи добре в повечето игрови сценарии.
### Представяне на правоъгълник
### Представяне с правоъгълник
Всеки игрови обект се нуждае от координатни граници, подобно на начина, по който марсоходът Mars Pathfinder картографира местоположението си на повърхността на Марс. Ето как определяме тези граници:
Всеки игрови обект се нуждае от координатни граници, подобно на това как марсоходът Mars Pathfinder маркира своето място на марсианската повърхност. Ето как дефинираме тези гранични координати:
```mermaid
flowchart TD
A["🎯 Игров обект"] --> B["📍 Позиция (x, y)"]
A --> C["📏 Размери (ширина, височина)"]
B --> D["Отгоре: y"]
B --> E["Ляво: x"]
C --> F["Отдолу: y + височина"]
C --> G["Дясно: x + ширина"]
D --> H["🔲 Правоъгълни граници"]
E --> H
F --> H
G --> H
H --> I["Готовност за засичане на сблъсъци"]
style A fill:#e3f2fd
style H fill:#e8f5e8
style I fill:#fff3e0
```
```javascript
rectFromGameObject() {
return {
@ -42,16 +109,38 @@ rectFromGameObject() {
}
```
**Нека разгледаме това:**
- **Горен ръб**: Това е просто мястото, където вашият обект започва вертикално (неговата y позиция)
- **Ляв ръб**: Където започва хоризонтално (неговата x позиция)
- **Долен ръб**: Добавете височината към y позицията - сега знаете къде свършва!
- **Десен ръб**: Добавете ширината към x позицията - и имате пълната граница
**Нека го разложим:**
- **Горна граница**: Това е просто къде започва вашият обект вертикално (неговата y позиция)
- **Лява граница**: Къде започва хоризонтално (неговата x позиция)
- **Долна граница**: Добавете височината към y позицията - сега знаете къде свършва!
- **Дясна граница**: Добавете ширината към x позицията - и имате пълните граници
### Алгоритъм за пресичане
Откриването на пресичане на правоъгълници използва логика, подобна на начина, по който космическият телескоп Хъбъл определя дали небесни обекти се припокриват в неговото зрително поле. Алгоритъмът проверява за разделение:
Откриването на пресичане на правоъгълници използва логика, подобна на тази, с която космическият телескоп Хъбъл определя дали небесни обекти се припокриват в неговото поле на видимост. Алгоритъмът проверява за разделение:
```mermaid
flowchart LR
A["Правоъгълник 1"] --> B{"Тестове за разделяне"}
C["Правоъгълник 2"] --> B
B --> D["Лявата страна на R2 > Дясната страна на R1?"]
B --> E["Дясната страна на R2 < Лявата страна на R1?"]
B --> F["Горната страна на R2 > Долната страна на R1?"]
B --> G["Долната страна на R2 < Горната страна на R1?"]
D --> H{"Някое вярно?"}
E --> H
F --> H
G --> H
H -->|Да| I["❌ Няма сблъсък"]
H -->|Не| J["✅ Засечен сблъсък"]
style B fill:#e3f2fd
style I fill:#ffebee
style J fill:#e8f5e8
```
```javascript
function intersectRect(r1, r2) {
return !(r2.left > r1.right ||
@ -62,30 +151,51 @@ function intersectRect(r1, r2) {
```
**Тестът за разделение работи като радарни системи:**
- Дали правоъгълник 2 енапълно вдясно от правоъгълник 1?
- Дали правоъгълник 2 енапълно вляво от правоъгълник 1?
- Дали правоъгълник 2 енапълно под правоъгълник 1?
- Дали правоъгълник 2 енапълно над правоъгълник 1?
- Дали правоъгълник 2 еизцяло вдясно от правоъгълник 1?
- Дали правоъгълник 2 еизцяло вляво от правоъгълник 1?
- Дали правоъгълник 2 еизцяло под правоъгълник 1?
- Дали правоъгълник 2 еизцяло над правоъгълник 1?
Ако нито едно от тези условия не е вярно, правоъгълниците трябва да се припокриват. Този подход отразява начина, по който операторите на радар определят дали два самолета са на безопасно разстояние.
Ако нито едно от тези условия не е вярно, правоъгълниците трябва да се припокриват. Този подход отразява как радарните оператори определят дали два самолета са на безопасно разстояние.
## Управление на жизнения цикъл на обектите
Когато лазер удари враг, и двата обекта трябва да бъдат премахнати от играта. Въпреки това, изтриването на обекти по време на цикъл може да причини сривове - урок, научен по трудния начин в ранните компютърни системи като компютъра за управление на Аполо. Вместо това използваме подход "маркиране за изтриване", който безопасно премахва обекти между кадрите.
Когато лазер удари враг, и двата обекта трябва да бъдат премахнати от играта. Обаче, изтриването на обекти в средата на цикъл може да предизвика сривове - урок научен трудно в ранните компютърни системи като Apollo Guidance Computer. Вместо това използваме подход "маркиране за изтриване", който безопасно премахва обекти между кадрите.
```mermaid
stateDiagram-v2
[*] --> Active: Обектът е създаден
Active --> Collided: Засечен е сблъсък
Collided --> MarkedDead: Задаване на dead = true
MarkedDead --> Filtered: Следващ кадър
Filtered --> [*]: Обектът е премахнат
Active --> OutOfBounds: Излиза от екрана
OutOfBounds --> MarkedDead
note right of MarkedDead
Безопасно е да продължите
текущия кадър
end note
note right of Filtered
Обекти са премахнати
между кадрите
end note
```
Ето как маркираме нещо за премахване:
```javascript
// Mark object for removal
// Маркирай обекта за премахване
enemy.dead = true;
```
**Защо този подход работи:**
- Маркираме обекта като "мъртъв", но не го изтриваме веднага
- Това позволява текущият игрови кадър да завърши безопасно
- Няма сривове от опити за използване на нещо, което вече е изтрито!
- Няма сривове от опити за използване на нещо, което вече липсва!
След това филтрираме маркираните обекти преди следващия цикъл на рендиране:
След това филтрираме маркираните обекти преди следващия цикъл за изобразяване:
- Предотвратява натрупването на памет от унищожени обекти
- Премахва всичко, маркирано като мъртво
- Поддържа играта ви да работи гладко
- Предотвратява натрупване на памет от унищожени обекти
## Внедряване на механика за лазери
## Имплементиране на лазерна механика
Лазерните снаряди в игрите работят на същия принцип като фотонните торпеда в "Стар Трек" - теса отделни обекти, които се движат по прави линии, докато ударят нещо. Всяко натискане на интервал създава нов лазерен обект, който се движи по екрана.
Лазерните снаряди в игрите работят по същия принцип като фотонните торпеда в Star Trek - товаса отделни обекти, които се движат по прави линии, докато не ударят нещо. Всяко натискане на space бар създава нов лазерен обект, който се движи по екрана.
За да направим това, трябва да координираме няколко различни елемента:
За да направим това, трябва да координираме няколко различни компонента:
**Основни компоненти за внедряване:**
**Основни компоненти за имплементация:**
- **Създаване** на лазерни обекти, които се появяват от позицията на героя
- **Обработка** на входа от клавиатурата за задействане на създаването на лазери
- **Управление** на движението и жизнения цикъл на лазерите
- **Внедряване** на визуално представяне за лазерните снаряди
- **Обработка** на клавиатурния вход за задействане на създаване на лазер
- **Управление** на движението и жизнения цикъл на лазера
- **Имплементиране** на визуално представяне за лазерните снаряди
## Внедряване на контрол на скоростта на стрелба
## Контрол на скоростта на стрелба
Неограничената скорост на стрелба би претоварила игровия двигател и би направила играта твърде лесна. Реалните оръжейни системи се сблъскват със сходни ограничения - дори фазерите на USS Enterprise се нуждаят от време за презареждане между изстрелите.
Неограничената скорост на стрелба би претоварила игровия двигател и би направила геймплея твърде лесен. Реалните оръжейни системи имат подобни ограничения — дори футуристичните фазери на USS Enterprise трябваше да се презареждат между изстрели.
Ще внедрим система за охлаждане, която предотвратява прекомерното стрелба, като същевременно поддържа отзивчиви контроли:
Ще имплементираме система за охлаждане, която предотвратява спамене с бързи изстрели, като същевременно запазва контролите отзивчиви:
```mermaid
sequenceDiagram
participant Player
participant Weapon
participant Cooldown
participant Game
Player->>Weapon: Натисни интервал
Weapon->>Cooldown: Провери дали е готово
alt Оружието е готово
Cooldown->>Weapon: готово = вярно
Weapon->>Game: Създай лазер
Weapon->>Cooldown: Стартирай ново охлаждане
Cooldown->>Cooldown: готово = невярно
Note over Cooldown: Изчакай 500мс
Cooldown->>Cooldown: готово = вярно
else Охлаждането е в ход
Cooldown->>Weapon: готово = невярно
Weapon->>Player: Няма действие
end
```
```javascript
class Cooldown {
constructor(time) {
@ -132,42 +266,58 @@ class Weapon {
fire() {
if (!this.cooldown || this.cooldown.cool) {
// Create laser projectile
// Създаване на лазерен снаряд
this.cooldown = new Cooldown(500);
} else {
// Weapon is still cooling down
// Оръжието все още се охлажда
}
}
}
```
**Как работи охлаждането:**
- Когато се създаде, оръжието започва "горещо" (не може да стреля веднага)
- След изтичане на времето за изчакване, става "охладено" (готово за стрелба)
- При създаване оръжието започва "гори" (не може да стреля веднага)
- След изтичане на време става "охладено" (готово за стрелба)
- Преди стрелба проверяваме: "Охладено ли е оръжието?"
- Това предотвратява прекомерното натискане на бутона, като същевременно запазва отзивчивостта на контрола
- Това предотвратява спам, като същевременно запазва контролите отзивчиви
✅ Прегледайте урок 1 от серията за космическа игра, за да си припомните системите за охлаждане.
✅ Върнете се към урок 1 в серията за космическата игра, за да си припомните за охлаждането.
## Създаване на система за откриване на сблъсъци
Ще разширите съществуващия код на вашата космическа игра, за да създадете система за откриване на сблъсъци. Подобно на автоматизираната система за избягване на сблъсъци на Международната космическа станция, вашата игра ще следи непрекъснато позициите на обектите и ще реагира на пресичания.
Ще разширите съществуващия код на вашата космическа игра, за да създадете система за откриване на сблъсъци. Подобно на автоматизирания механизъм за избягване на сблъсъци на Международната космическа станция, вашата игра ще следи непрекъснато позициите на обектите и ще реагира на пресичания.
Започвайки от кода от предишния урок, ще добавите откриване на сблъсъци със специфични правила, които управляват взаимодействията между обектите.
Започвайки от кода от предишния урок, ще добавите откриване на сблъсъци с конкретни правила, които управляват взаимодействията на обектите.
> 💡 **Съвет**: Спрайтът на лазера вече е включен в папката с активи и е рефериран в кода ви, готов за внедряване.
> 💡 **Професионален съвет**: Лазерният спрайт вече е включен във вашата папка с ресурси и е препратен в кода ви, готов за имплементация.
### Правила за сблъсъци, които да се внедрят
### Правила за сблъсъци за имплементиране
**Игрова механика за добавяне:**
1. **Лазер удря враг**: Вражеският обект се унищожава, когато бъде ударен от лазерен снаряд
2. **Лазер удря границата на екрана**: Лазерът се премахва, когато достигне горния ръб на екрана
**Игрови механики, които да добавите:**
1. **Лазер удря враг**: Враговият обект се унищожава при удар от лазерен снаряд
2. **Лазер удря границата на екрана**: Лазерът се премахва при достигане на горната граница на екрана
3. **Сблъсък между враг и герой**: И двата обекта се унищожават при пресичане
4. **Враг достига дъното**: Условие за край на играта, когато враговете достигнат дъното на екрана
4. **Враг достига дъното**: Условие за край на играта, когато враговете достигнат долната част на екрана
### 🔄 **Педагогическа Проверка**
**Основи на Откриването на Сблъсъци**: Преди имплементация се уверете, че разбирате:
- ✅ Как границите на правоъгълниците дефинират зоните на сблъсък
- ✅ Защо тестът за разделение е по-ефективен от изчислението на пресичането
- ✅ Значението на управлението на жизнения цикъл на обектите в игровите цикли
- ✅ Как системите, управляеми от събития, координират реакциите при сблъсъци
**Бърз Самотест**: Какво би се случило, ако изтриете обекти веднага вместо да ги маркирате?
*Отговор: Изтриването по средата на цикъла може да предизвика сривове или прескача обекти при итерация*
## Настройка на вашата среда за разработка
**Разбиране на Физиката**: Вече разбирате:
- **Координатни Системи**: Как позицията и размерите създават граници
- **Логика на Пресичане**: Математически принципи зад откриването на сблъсъци
- **Оптимизация на Работата**: Защо ефективните алгоритми са важни за системи в реално време
- **Управление на Паметта**: Безопасни модели на жизнен цикъл на обектите за стабилност
Добри новини - вече сме подготвили по-голямата част от основата за вас! Всички ваши игрови активи и основна структура са готови в поддиректорията `your-work`, готови за добавяне на страхотните функции за откриване на сблъсъци.
## Настройване на средата за разработка
Добри новини - вече сме подготвили повечето от основите за вас! Всички ваши игрови ресурси и базова структура чакат в поддиректорията `your-work`, готови за добавянето на страхотните функции за сблъсъци.
### Структура на проекта
@ -182,13 +332,13 @@ class Weapon {
```
**Разбиране на структурата на файловете:**
- **Съдържа** всички изображения на спрайтове, необходими за игровите обекти
- **Включва** основния HTML документ и JavaScript файл за приложението
- **Съдържа** всички спрайт изображения, нужни за игровите обекти
- **Включва** основния HTML документ и JavaScript приложението
- **Осигурява** конфигурация на пакета за локален сървър за разработка
### Стартиране на сървъра за разработка
Навигирайте до папката на проекта и стартирайте локалния сървър:
Отидете до папката на проекта и стартирайте локалния сървър:
```bash
cd your-work
@ -196,20 +346,45 @@ npm start
```
**Тази последователност от команди:**
- **Променя** директорията към работната папка на проекта
- **Променя** директорията във вашата работна папка
- **Стартира** локален HTTP сървър на `http://localhost:5000`
- **Сервира** вашите игрови файлове за тестване и разработка
- **Позволява** разработка вреално времес автоматично презареждане
- **Сервира** вашите игрови файлове за тест и разработка
- **Позволява** живо разработване с автоматично презареждане
Отворете браузъра си и навигирайте до`http://localhost:5000`, за да видите текущото състояние на играта си с героя и враговете, изобразени на екрана.
Отворете браузъра и посетете`http://localhost:5000`, за да видите текущото състояние на играта с визуализирани герой и врагове на екрана.
### Стъпка по стъпка внедряване
### Имплементация стъпка по стъпка
Подобно на систематичния подход, който НАСА използва за програмиране на космическия кораб Voyager, ще внедрим системата за откриване на сблъсъци методично, като изграждаме всеки компонент стъпка по стъпка.
Както систематичния подход на НАСА за програмиране на космическите апарати Voyager, ще имплементираме откриването на сблъсъци методично, изграждайки всяка част по етапи.
#### 1. Добавяне на граници за сблъсък на правоъгълници
```mermaid
flowchart TD
A["1. Граници на правоъгълник"] --> B["2. Засичане на пресичане"]
B --> C["3. Лазерна система"]
C --> D["4. Обработка на събития"]
D --> E["5. Правила за сблъсък"]
E --> F["6. Система за охлаждане"]
G["Граници на обект"] --> A
H["Физичен алгоритъм"] --> B
I["Създаване на снаряди"] --> C
J["Въвеждане от клавиатура"] --> D
K["Игрова логика"] --> E
L["Ограничаване на скоростта"] --> F
F --> M["🎮 Завършена игра"]
style A fill:#e3f2fd
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#e0f2f1
style F fill:#fce4ec
style M fill:#e1f5fe
```
#### 1. Добавяне на правоъгълни граници за сблъсък
Първо, нека научим нашите игрови обекти как да описват своите граници. Добавете този метод към вашия клас `GameObject`:
Първо, нека научим игровите обекти как да описват своите граници. Добавете този метод към класа`GameObject`:
```javascript
rectFromGameObject() {
@ -224,13 +399,13 @@ rectFromGameObject() {
**Този метод постига:**
- **Създава** правоъгълен обект с точни координати на границите
- **Изчислява** долния и десния ръб, използвайки позиция плюс размери
- **Връща** обект, готов за алгоритми за откриване на сблъсъци
- **Изчислява** долната и дясната граница чрез позиция + размери
- **Връща** обект, готов за алгоритми за откриване на сблъсък
- **Осигурява** стандартизиран интерфейс за всички игрови обекти
#### 2. Внедряване на откриване на пресичане
#### 2. Имплементиране на откриване на пресичане
Сега нека създадем нашия детектив за сблъсъци - функция, която може да каже кога два правоъгълника се припокриват:
Сега нека създадем нашия детектор за сблъсъци - функция, която може да определи кога два правоъгълника се припокриват:
```javascript
function intersectRect(r1, r2) {
@ -244,18 +419,18 @@ function intersectRect(r1, r2) {
```
**Този алгоритъм работи чрез:**
- **Тества** четири условия за разделение между правоъгълниците
- **Тества** четири условия за разделение между правоъгълници
- **Връща** `false`, ако някое условие за разделение е вярно
- **Показва** сблъсък, когато няма разделение
- **Използва** логика на отрицание за ефективно тестване на пресичане
- **Индикира** сблъсък, когато разделение липсва
- **Използва** логика на отрицание за ефективно тестиране на пресичане
#### 3. Внедряване на система за стрелба с лазери
#### 3. Имплементиране на система за стрелба с лазер
Тук става интересно! Нека настроим системата за стрелба с лазери.
Тук нещата стават вълнуващи! Нека настроим системата за стрелба с лазер.
##### Константи за съобщения
Първо, нека дефинираме някои типове съобщения, за да могат различните части на нашата игра да комуникират помежду си:
Първо, нека дефинираме някои типове съобщения, за да могат различните части на играта да комуникират помежду си:
if (intersectRect(laser.rectFromGameObject(), enemy.rectFromGameObject())) {
@ -367,20 +542,20 @@ function updateGameObjects() {
});
});
// Remove destroyed objects
// Премахнете разрушените обекти
gameObjects = gameObjects.filter(go => !go.dead);
}
```
**Тази система за сблъсъци:**
- **Филтрира** игровите обекти по тип за ефективно тестване
- **Тества** всеки лазер срещу всеки враг за пресичания
- **Изпраща** събития за сблъсък, когато се открият пресичания
- **Почиства** унищожените обекти след обработка на сблъсъци
- **Филтрира** игрови обекти по тип за ефективно тестване
- **Тества** всеки лазер срещу всеки враг за пресичане
- **Излъчва** събития при засичане на сблъсък
- **Почиствa** унищожени обекти след обработка на сблъсъците
> ⚠️ **Важно**: Добавете `updateGameObjects()`към основния цикъл на играта в `window.onload`, за да активирате откриването на сблъсъци.
> ⚠️ **Важно**: Добавете `updateGameObjects()`във вашия главен игрови цикъл в `window.onload` за активиране на откриването на сблъсъци.
#### 6. Добавяне на система за охлаждане към класа Hero
#### 6. Добавяне на система за охлаждане в класа Hero
Подобрете класа Hero с механика за стрелба и ограничаване на скоростта:
@ -414,18 +589,188 @@ class Hero extends GameObject {
}
```
**Разбиране на подобрения клас Hero:**
- **Инициира** таймер за охлаждане на нула (готов за стрелба)
**Как раздразненото Hero работи:**
- **Инициализира** таймер за охлаждане на нула (готов за стрелба)
- **Създава** лазерни обекти, позиционирани над кораба на героя
- **Задава** период на охлаждане, за да предотврати прекомерно стрелба
- **Намалява** таймера за охлаждане с актуализации на базата на интервали
- **Осигурява** проверка на състоянието на стрелба чрез метода `canFire()`
- **Задава** период на охлаждане, за да предотврати бързи изстрели
- **Намалява** таймера чрез интервални ъпдейти
- **Осигурява** метод `canFire()` за проверка дали може да стреля
### 🔄 **Педагогическа Проверка**
**Пълно Разбиране на Системата**: Проверете натрупаните си знания за системата за сблъсъци:
- ✅ Как границите на правоъгълниците позволяват ефективно откриване на сблъсъци?
- ✅ Защо управлението на жизнения цикъл на обекти е критично за стабилността на играта?
- ✅ Как системата за охлаждане предотвратява проблеми с производителността?
- ✅ Каква роля играе архитектурата, управляемa от събития, при обработката на сблъсъци?
**Интеграция на Системата**: Вашата система за откриване на сблъсъци демонстрира:
- **Математическа Точност**: Алгоритми за пресичане на правоъгълници
- **Оптимизация на Работата**: Ефективни модели за тестване на сблъсъци
- **Управление на Паметта**: Безопасно създаване и унищожаване на обекти
- **Координация на Събития**: Отделена системна комуникация
- **Обработка в Реално Време**: Ъпдейти базирани на кадри
**Професионални Модели**: Имплементирали сте:
- **Разделение на Отговорностите**: Физика, рендериране и вход разделени
- **Обектно-Ориентиран Дизайн**: Наследяване и полиморфизъм
- **Управление на Състоянието**: Проследяване на жизнения цикъл на обекти и състоянието на играта
- **Оптимизация на Изпълнението**: Ефективни алгоритми за употреба в реално време
### Тестване на имплементацията
Вашата космическа игра вече разполага с пълна система за откриване на сблъсъци и бойна механика. 🚀 Тествайте новите възможности:
- **Навигирайте** с клавишите със стрелки за проверка на управлението на движението
- **Стреляйте с лазери** с space bar — забележете как системата за охлаждане предотвратява спам
- **Наблюдавайте сблъсъците**, когато лазерите удрят врагове и те се премахват
- **Проверете почистването** като унищожените обекти изчезват от играта
Успешно имплементирахте система за откриване на сблъсъци, използвайки същите математически принципи, които управляват навигацията на космически кораби и роботика.
### ⚡ **Какво можете да направите през следващите 5 минути**
- [ ] Отворете DevTools на браузъра и поставете прекъсвачи в функцията за откриване на сблъсъци
- [ ] Опитайте да промените скоростта на лазера или движението на врага, за да видите ефектите от сблъсъците
- [ ] Експериментирайте с различни стойности на охлаждане, за да тествате скоростта на стрелба
- [ ] Добавете `console.log` изрази за проследяване на събития с колизии в реално време
### 🎯 **Какво можете да постигнете този час**
- [ ] Попълване на теста след урока и разбиране на алгоритмите за засичане на колизии
- [ ] Добавяне на визуални ефекти като експлозии при възникване на колизии
- [ ] Имплементиране на различни видове снаряди с различни характеристики
- [ ] Създаване на бустъри, които временно усилват способностите на играча
- [ ] Добавяне на звукови ефекти, за да направите колизиите по-удовлетворяващи
### 📅 **Вашият седмичен план за физично програмиране**
- [ ] Завършване на цялата космическа игра с усъвършенствани системи за колизии
- [ ] Имплементиране на разширени форми за колизии извън правоъгълници (кръгове, полигони)
- [ ] Добавяне на частици за реалистични експлозивни ефекти
- [ ] Създаване на сложни поведения на враговете с избягване на колизии
- [ ] Оптимизиране на засичането на колизии за по-добра производителност при много обекти
- [ ] Добавяне на физическа симулация като инерция и реалистично движение
### 🌟 **Вашият месечен курс по майсторство на игра с физика**
- [ ] Създаване на игри с напреднали физични двигатели и реалистични симулации
- [ ] Изучаване на 3D засичане на колизии и алгоритми за пространствено разделяне
- [ ] Принос към отворени библиотеки за физика и игрови двигатели
- [ ] Майсторство в оптимизация на производителността за графично натоварващи приложения
- [ ] Създаване на образователно съдържание за игрова физика и засичане на колизии
- [ ] Изграждане на портфолио, демонстриращо напреднали умения по програмиране на физика
## 🎯 Времева линия за вашето майсторство в засичането на колизии
```mermaid
timeline
title Напредък в изучаването на засичане на сблъсъци и игрова физика
section Основи (10 минути)
Rectangle Math: Координатни системи
: Изчисляване на граници
: Следене на позиция
: Управление на размери
section Проектиране на алгоритъм (20 минути)
Intersection Logic: Тест за разделяне
: Засичане на припокриване
: Оптимизация на производителността
: Обработка на гранични случаи
section Имплементация на игра (30 минути)
Object Systems: Управление на жизнения цикъл
: Координация на събития
: Следене на състояние
: Почистване на памет
section Интерактивни функции (40 минути)
Combat Mechanics: Системи за проектили
: Време за презареждане на оръжия
: Изчисляване на щети
: Визуална обратна връзка
section Разширена физика (50 минути)
Real-time Systems: Оптимизация на честота на кадрите
: Пространствено разделяне
: Реакция при сблъсък
: Физическа симулация
section Професионални техники (1 седмица)
Game Engine Concepts: Системи от компоненти
: Физични процеси
: Профилиране на производителността
: Кросплатформена оптимизация
section Индустриални приложения (1 месец)
Production Skills: Оптимизация в голям мащаб
: Екипно сътрудничество
: Разработка на игров енджин
: Деплоймънт на платформа
```
### 🛠️ Обобщение на вашия набор от инструменти за игрова физика
След завършване на този урок сте овладели:
- **Математика на колизии**: Алгоритми за пресичане на правоъгълници и координатни системи
- **Оптимизация на производителността**: Ефективно засичане на колизии за приложения в реално време
- **Управление на жизнения цикъл на обекти**: Безопасно създаване, обновяване и унищожаване на обекти
- **Архитектура, базирана на събития**: Отделени системи за реакция на колизии
- **Интеграция в игровия цикъл**: Физични обновявания на кадър и координация на рендера
- **Входни системи**: Отзивчиви контроли с ограничение на скоростта и обратна връзка
- **Управление на паметта**: Ефективно използване на обектни плувове и почистване
**Приложения в реалния свят**: Уменията за засичане на колизии могат директно да се прилагат в:
- **Интерактивни симулации**: Научно моделиране и образователни инструменти
- **Дизайн на потребителски интерфейс**: Влачене и пускане, засичане на докосвания
- **Визуализация на данни**: Интерактивни графики и кликващи елементи
- **Мобилна разработка**: Разпознаване на жестове и обработка на колизии
- **Роботика**: Планиране на път и избягване на препятствия
- **Компютърна графика**: Лъчево проследяване и пространствени алгоритми
**Професионални умения, придобити**: Сега можете да:
- **Проектирате** ефективни алгоритми за засичане на колизии в реално време
- **Имплементирате** физични системи, адаптиращи се според сложността на обектите
- **Отстранявате грешки** в сложни системи за взаимодействие чрез математически принципи
- **Оптимизирате** производителността за различен хардуер и браузъри
- **Архитектирате** поддържани игрови системи чрез утвърдени дизайнерски модели
**Овладени концепции в разработката на игри**:
- **Физическа симулация**: Засичане на колизии и реакция в реално време
- **Инженерство на производителността**: Оптимизирани алгоритми за интерактивни приложения
- **Системи със събития**: Разделена комуникация между компонентите на играта
- **Управление на обектите**: Ефективни шаблони за жизнения цикъл на динамично съдържание
- **Обработка на вход**: Отзивчиви контроли с адекватна обратна връзка
**Следващо ниво**: Готови сте да изследвате напреднали физични двигатели като Matter.js, да имплементирате 3D засичане на колизии или да създавате сложни системи с частици!
🌟 **Постижение отключено**: Изградихте цяла система за взаимодействия, базирана на физика с професионално качество в засичането на колизии!
## GitHub Copilot Agent Challenge 🚀
Използвайте режим Agent, за да изпълните следното предизвикателство:
**Описание:** Подобрете системата за засичане на колизии, като имплементирате бустъри, които се появяват случайно и осигуряват временно усилване при събиране от героя.
**Подсказка:** Създайте клас PowerUp, който наследява GameObject и имплементира засичане на колизии между героя и бустърите. Добавете поне два типа бустъри: един, който увеличава скоростта на стрелба (намалява време на презареждане), и друг, който създава временен щит. Включете логика за появяване на бустъри на случайни интервали и позиции.
---
## 🚀 Предизвикателство
Добавете експлозия! Разгледайте игровите ресурси в [the Space Art repo](../../../../6-space-game/solution/spaceArt/readme.txt) и опитайте да добавите експлозия, когато лазерът удари извънземен
Експериментирайте с интервалите в играта досега. Какво се случва, когато ги промените? Прочетете повече за [JavaScript таймингови събития](https://www.freecodecamp.org/news/javascript-timing-events-settimeout-and-setinterval/).
### Тестване на вашата имплементация
## Задача
Вашата космическа игра вече разполага с пълна система за открив
[Explore collisions](assignment.md)
---
**Отказ от отговорност**:
Този документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Не носим отговорност за недоразумения или погрешни интерпретации, произтичащи от използването на този превод.
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Отказ от отговорност**:
Този документ е преведен с помощта на AI преводаческа услуга [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на родния му език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за никакви недоразумения или неправилни тълкувания, произтичащи от използването на този превод.
Готови ли сте да направите вашата космическа игра да се усеща като истинска игра? Нека добавим точки и управление на животи - основните механики, които превърнаха ранните аркадни игри като Space Invaders от прости демонстрации в пристрастяващо забавление. Тук вашата игра става наистина игрална.
## Рисуване на текст на екрана - Гласът на вашата игра
# Изграждане на космическа игра Част 5: Точки и животи
```mermaid
journey
title Вашето пътешествие в дизайна на игри
section Обратна връзка от играчи
Разбиране на психологията на оценяването: 3: Student
Научаване на визуална комуникация: 4: Student
Проектиране на системи за награди: 4: Student
section Техническа реализация
Рендиране на текст в Canvas: 4: Student
Управление на състоянието: 5: Student
Актуализации, задвижвани от събития: 5: Student
section Финализиране на играта
Проектиране на потребителско преживяване: 5: Student
Балансиране на предизвикателство и награда: 5: Student
Създаване на ангажираща игрова механика: 5: Student
```
## Куиз преди лекцията
[Куиз преди лекцията](https://ff-quizzes.netlify.app/web/quiz/37)
Готови ли сте да направите космическата си игра да се усеща като истинска игра? Нека добавим трупане на точки и управление на животи - основните механики, които превърнаха ранните аркадни игри като Space Invaders от прости демонстрации в пристрастяващо забавление. Тук вашата игра става наистина играема.
```mermaid
mindmap
root((Системи за обратна връзка в игрите))
Визуална комуникация
Рендиране на текст
Показване на икони
Психология на цвета
Дизайн на оформление
Механики за оценяване
Точки
Време за награда
Проследяване на прогреса
Системи за постижения
Управление на живота
Риск срещу награда
Агентност на играча
Баланс на трудността
Механики за възстановяване
Потребителско изживяване
Незабавна обратна връзка
Ясна информация
Емоционален отговор
Цикли на ангажираност
Имплементация
Canvas API
Управление на състоянието
Системи за събития
Изпълнение
```
## Рисуване на текст на екрана - гласът на вашата игра
За да покажем вашите точки, трябва да научим как да изобразяваме текст върху канваса. Методът `fillText()`е основният ви инструмент за това - същата техника, използвана в класическите аркадни игри за показване на точки и информация за статуса.
За да покажем вашия резултат, трябва да научим как да изобразяваме текст върху канваса. Методът `fillText()`е основният ви инструмент за това - същата техника, използвана в класическите аркадни игри за показване на точки и статусна информация.
Имате пълен контрол върху външния вид на текста:
```mermaid
flowchart LR
A["📝 Текстово съдържание"] --> B["🎨 Стил"]
B --> C["📍 Позициониране"]
C --> D["🖼️ Рендер на платно"]
E["Шрифт"] --> B
F["Размер на шрифта"] --> B
G["Цвят"] --> B
H["Подравняване"] --> B
I["X Координата"] --> C
J["Y Координата"] --> C
style A fill:#e3f2fd
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#f3e5f5
```
Вие имате пълен контрол върху външния вид на текста:
```javascript
ctx.font = "30px Arial";
@ -28,24 +92,74 @@ ctx.textAlign = "right";
ctx.fillText("show this on the screen", 0, 0);
```
✅ Разгледайте по-подробно [добавянето на текст към канвас](https://developer.mozilla.org/docs/Web/API/Canvas_API/Tutorial/Drawing_text) - може да се изненадате колко креативни можете да бъдете с шрифтове и стилове!
✅ Потопете се по-дълбоко в [добавяне на текст към канвас](https://developer.mozilla.org/docs/Web/API/Canvas_API/Tutorial/Drawing_text) – може да се изненадате колко креативни може да станете с шрифтове и стилове!
## Животи - Повече от просто число
В дизайна на игри, "живот" представлява маржът за грешка на играча. Тази концепция датира от пинбол машините, където получавахте няколко топки за игра. В ранните видеоигри като Asteroids, животите даваха на играчите разрешение да поемат рискове и да се учат от грешките си.
В дизайна на игри „животът“ представлява допустимата грешка на играча. Тази концепция датира още от машините за пинбол, където разполагаш с няколко топки за игра. В ранните видеоигри като Asteroids, животите дават право на играчите да поемат рискове и да се учат от грешките си.
Визуалното представяне е от голямо значение - показването на икони на кораби вместо просто "Животи: 3" създава незабавно визуално разпознаване, подобно на начина, по който ранните аркадни машини използваха иконография, за да комуникират отвъд езиковите бариери.
```mermaid
flowchart TD
A["🎮 Играчко действие"] --> B{"Оценка на риска"}
B --> C["Висок риск, висока награда"]
B --> D["Безопасна стратегия"]
C --> E{"Резултат"}
D --> F["Постепенен напредък"]
E -->|Успех| G["🏆 Големи точки"]
E -->|Провал| H["💔 Загуби живот"]
H --> I{"Оставащи животи?"}
I -->|Да| J["🔄 Опитай отново"]
I -->|Не| K["💀 Край на играта"]
J --> B
G --> B
F --> B
style C fill:#ffebee
style D fill:#e8f5e8
style G fill:#e3f2fd
style H fill:#fff3e0
```
Визуалното представяне е изключително важно - показването на икони на кораби вместо просто "Животи: 3" създава незабавно визуално разпознаване, подобно на това как ранните аркадни шкафове използваха икони, за да комуникират през езикови бариери.
## Създаване на система за награди в играта
## Създаване на системата за награди в играта ви
Сега ще внедрим основните системи за обратна връзка, които държат играчите ангажирани:
Сега ще реализираме основните системи за обратна връзка, които държат играчите ангажирани:
- **Система за точки**: Всеки унищожен вражески кораб носи 100 точки (кръглите числа са по-лесни за умствено изчисление от играчите). Точките се показват в долния ляв ъгъл.
- **Брояч на животи**: Вашият герой започва с три живота - стандарт, установен от ранните аркадни игри за балансиране на предизвикателството с играемостта. Всяко сблъскване с враг струва един живот. Ще покажем оставащите животи в долния десен ъгъл, използвайки икони на кораби .
```mermaid
sequenceDiagram
participant Player
participant GameEngine
participant ScoreSystem
participant LifeSystem
participant Display
Player->>GameEngine: Изстрелва Враг
GameEngine->>ScoreSystem: Награждава точки
ScoreSystem->>ScoreSystem: +100 точки
ScoreSystem->>Display: Актуализира резултата
Player->>GameEngine: Сблъсква сесВраг
GameEngine->>LifeSystem: Губи живот
LifeSystem->>LifeSystem: -1 живот
LifeSystem->>Display: Актуализира животи
alt Животи > 0
LifeSystem->>Player: Продължава да играе
else Животи = 0
LifeSystem->>GameEngine: Край на играта
end
```
- **Система за точкуване**: Всеки унищожен вражески кораб дава 100 точки (кръглите числа са по-лесни за умствена аритметика от играчите). Резултатът се показва в долния ляв ъгъл.
- **Брояч животи**: Вашият герой започва с три живота - стандарт, установен от ранните аркадни игри за балансиране на предизвикателството с играбилността. Всяко сблъскване с враг отнема един живот. Ще показваме оставащите животи в долния десен ъгъл с икони на кораби .
## Да започваме!
## Да започваме да градим!
Първо, подгответе работното си пространство. Навигирайте до файловете в папката `your-work`. Трябва да видите тези файлове:
Първо настройте работната си среда. Отидете до файловете в подпапката `your-work`. Трябва да видите тези файлове:
```bash
-| assets
@ -57,24 +171,49 @@ ctx.fillText("show this on the screen", 0, 0);
-| package.json
```
За да тествате играта си, стартирайте сървъра за разработка от папката `your_work`:
За да тествате играта, стартирайте сървъра за разработка от папката `your_work`:
```bash
cd your-work
npm start
```
Това ще стартира локален сървър на адрес`http://localhost:5000`. Отворете този адрес в браузъра си, за да видите играта. Тествайте управлението с клавишите със стрелки и опитайте да стреляте по враговете, за да проверите дали всичко работи.
Това стартира локален сървър на `http://localhost:5000`. Отворете този адрес в браузъра си, за да видите играта. Тествайте управлението с клавишите със стрелки и опитайте да стреляте по врагове, за да проверите дали всичко работи.
### Време за кодиране!
```mermaid
flowchart TD
A["1. Зареждане на ресурси"] --> B["2. Игрови променливи"]
B --> C["3. Засичане на сблъсъци"]
C --> D["4. Подобрение на героя"]
D --> E["5. Функции за показване"]
E --> F["6. Обработващи събитията"]
G["Изображение на икона за живот"] --> A
H["Отчитане на точки и животи"] --> B
I["Пресичания герой-враг"] --> C
J["Методи за точки и живот"] --> D
K["Рендиране на текст и икона"] --> E
L["Логика за награди и наказания"] --> F
F --> M["🎮 Завършена игра"]
style A fill:#e3f2fd
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#e0f2f1
style F fill:#fce4ec
style M fill:#e1f5fe
```
### Време за код!
1. **Вземете визуалните ресурси, които ще ви трябват**. Копирайте ресурса`life.png` от папката `solution/assets/` в папката `your-work`. След това добавете lifeImg към функцията си window.onload:
1. **Вземете необходимите визуални активи**. Копирайте файла `life.png` от папката `solution/assets/` в `your-work` папката. След това добавете lifeImg във функцията window.onload:
```javascript
lifeImg = await loadTexture("assets/life.png");
```
1. Не забравяйте да добавите `lifeImg` към списъка с ресурси:
1. Не забравяйте да добавите `lifeImg` към списъка сактиви:
```javascript
let heroImg,
@ -84,9 +223,9 @@ npm start
eventEmitter = new EventEmitter();
```
2. **Настройте променливите на играта**. Добавете малко код за проследяване на общия брой точки (започвайки от 0) и оставащите животи (започвайки от 3). Ще ги показваме на екрана, за да знаят играчите винаги къде се намират.
2. **Настройте игровите променливи**. Добавете код за проследяване на общия резултат (стартиращ от 0) и останалите животи (стартиращи от 3). Ще показваме тези стойности на екрана, за да знаят играчите винаги къде се намират.
3. **Внедрете откриване на сблъсъци**. Разширете функцията си `updateGameObjects()`, за да открива кога враговете се сблъскват с вашия герой:
3. **Реализирайте откриване на сблъсъци**. Разширете функцията `updateGameObjects()`, за да засича сблъсъци между врагове и героя:
```javascript
enemies.forEach(enemy => {
@ -97,15 +236,15 @@ npm start
})
```
4. **Добавете проследяване на животи и точки към вашия герой**.
1. **Инициализирайте броячите**. Под `this.cooldown = 0` в класа `Hero`, настройте животите и точките:
4. **Добавете проследяване на животи и точки към героя**.
1. **Инициализирайте броячите**. Под `this.cooldown = 0` в класа `Hero` настройте живот и точки:
```javascript
this.life = 3;
this.points = 0;
```
1. **Покажете тези стойности на играча**. Създайте функции за изобразяване на тези стойности на екрана:
1. **Показвайте тези стойности на играча**. Създайте функции за рисуване на тези стойности на екрана:
```javascript
function drawLife() {
@ -132,18 +271,34 @@ npm start
```
1. **Свържете всичко с игровия цикъл**. Добавете тези функции към функцията си window.onload веднага след `updateGameObjects()`:
1. **Свържете всичко с игровия цикъл**. Добавете тези функции във функцията window.onload веднага след `updateGameObjects()`:
```javascript
drawPoints();
drawLife();
```
1. **Внедрете последствия и награди в играта**. Сега ще добавим системите за обратна връзка, които правят действията на играча значими:
### 🔄 **Педагогическо сверяване**
**Разбиране на дизайн на играта**: Преди да реализирате последствия, уверете се, че разбирате:
- ✅ Как визуалната обратна връзка комуникира игровото състояние към играчите
- ✅ Защо последователното разположение на елементите от UI подобрява удобството
- ✅ Психологията зад стойностите на точките и управлението на животите
- ✅ Как рисуването на текст върху канваса се различава от HTML текст
**Бърз само-тест**: Защо аркадните игри обикновено използват кръгли числа за точките?
*Отговор: Кръглите числа са по-лесни за умствено пресмятане от играчите и създават удовлетворяващи психологически награди*
**Принципи на потребителския опит**: Вече прилагате:
- **Визуална йерархия**: Важна информация позиционирана на видно място
- **Незабавна обратна връзка**: Актуализации в реално време на действията на играча
- **Когнитивно натоварване**: Простичко и ясно представяне на информацията
- **Емоционален дизайн**: Икони и цветове, които създават връзка с играча
1. **Сблъсъците струват животи**. Всеки път, когато вашият герой се сблъска с враг, трябва да загубите един живот.
1. **Реализирайте последици и награди в играта**. Сега ще добавим системите за обратна връзка, които правят действията на играча значими:
1. **Сблъсъците струват животи**. Всеки път, когато вашият герой се сблъска с враг, трябва да загуби живот.
Добавете този метод към класа си `Hero`:
Добавете този метод в класа`Hero`:
```javascript
decrementLife() {
@ -154,9 +309,9 @@ npm start
}
```
2. **Стрелбата по врагове носи точки**. Всеки успешен удар носи 100 точки, предоставяйки незабавна положителна обратна връзка за точната стрелба.
2. **Стрелбата по врагове носи точки**. Всяко успешно попадение дава 100 точки, осигурявайки незабавна положителна обратна връзка за точната стрелба.
Разширете класа си Hero с този метод за увеличаване:
Разширете класа Hero с този метод за увеличаване на точките:
```javascript
incrementPoints() {
@ -164,7 +319,7 @@ npm start
}
```
Сега свържете тези функции със събитията за сблъсък:
Сега свържете тези функции със събитията на сблъсък:
```javascript
eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => {
@ -179,41 +334,177 @@ npm start
});
```
✅ Любопитни ли сте за други игри, създадени с JavaScript и Canvas? Разгледайте - може да се изненадате какво е възможно!
След като внедрите тези функции, тествайте играта си, за да видите пълната система за обратна връзка в действие. Трябва да видите икони на животи в долния десен ъгъл, вашите точки в долния ляв ъгъл и да наблюдавате как сблъсъците намаляват животите, докато успешните изстрели увеличават точките.
Вашата игра вече има основните механики, които направиха ранните аркадни игри толкова завладяващи - ясни цели, незабавна обратна връзка и значими последствия за действията на играча.
✅ Любопитни сте за други игри, изградени с JavaScript и Canvas? Изследвайте – може да се изненадате какво е възможно!
След като приложите тези функции, тествайте играта си, за да видите как работи цялата система за обратна връзка. Трябва да видите икони за животите в долния десен ъгъл, резултата в долния ляв, и да наблюдавате как сблъсъците намаляват животи, докато успешните изстрели увеличават точките.
Вашата игра вече има съществените механики, които направиха ранните аркадни игри толкова увлекателни - ясни цели, незабавна обратна връзка и значими последици за действията на играча.
### 🔄 **Педагогическо сверяване**
**Пълна система за дизайн на игра**: Проверете овладяването си на системите за обратна връзка с играчите:
- ✅ Как механиките за точкуване създават мотивация и ангажираност на играча?
- ✅ Защо визуалната последователност е важна за дизайна на интерфейс?
- ✅ Как системата с животи балансира предизвикателството с задържането на играча?
- ✅ Каква роля играе незабавната обратна връзка за удовлетворяващ геймплей?
**Интеграция на системи**: Вашата система за обратна връзка демонстрира:
- **Дизайн на потребителския опит**: Ясна визуална комуникация и информационна йерархия
- **Архитектура, базирана на събития**: Отзивчиви актуализации за действията на играча
- **Управление на състоянието**: Проследяване и визуализация на динамични игрови данни
- **Майсторство на канваса**: Рендиране на текст и позициониране на спрайтове
- **Психология на играта**: Разбиране на мотивацията и ангажираността на играча
**Професионални модели**: Прилагате:
- **MVC архитектура**: Разделяне на игровата логика, данни и представяне
- **Наблюдателен модел**: Актуализации, задвижвани от събития, за промени в игровото състояние
- **Дизайн на компоненти**: Преустройстваеми функции за рендиране и логика
- **Оптимизация на производителността**: Ефикасно рендиране в игрови цикли
### ⚡ **Какво може да направите през следващите 5 минути**
- [ ] Експериментирайте с различни размери шрифтове и цветове за показване на резултата
- [ ] Опитайте да промените стойностите на точките и наблюдавайте как това влияе на усещането от играта
- [ ] Добавете console.log изявления, за да следите кога точките и животите се променят
- [ ] Тествайте гранични случаи като свършват животи или постигане на високи резултати
### 🎯 **Какво може да постигнете този час**
- [ ] Попълнете теста след урока и разберете психологията на дизайна на игрите
- [ ] Добавете звукови ефекти за трупане на точки и загуба на животи
- [ ] Реализирайте система за висок резултат чрез localStorage
- [ ] Създайте различни стойности за точки за различни видове врагове
- [ ] Добавете визуални ефекти като разтърсване на екрана при загуба на живот
### 📅 **Вашето седмично пътуване в дизайна на игри**
- [ ] Завършете цялата космическа игра с усъвършенствани системи за обратна връзка
- [ ] Реализирайте сложни системи за точкуване като множители за комбо
- [ ] Добавете постижения и отключващо се съдържание
- [ ] Създайте системи за прогрес и балансиране на трудността
- [ ] Проектирайте потребителски интерфейси за менюта и екрани за край на играта
- [ ] Изучете други игри, за да разберете механизмите за ангажиране
### 🌟 **Вашето месечно овладяване на разработката на игри**
- [ ] Построете пълни игри със сложни системи за прогрес
- [ ] Научете анализ на игри и измерване на поведение на играчите
- [ ] Приносете в отворени проекти за разработка на игри
- [ ] Овладейте напреднали модели на дизайн и монетизация в игрите
- [ ] Създавайте образователно съдържание за дизайн на игри и потребителски опит
- [ ] Създайте портфолио, показващо уменията ви в дизайн и разработка на игри
## 🎯 Вашият времеви график за овладяване на дизайна на игри
```mermaid
timeline
title Прогрес на обучението по дизайн на игри и обратна връзка от играчи
section Основи (10 минути)
Визуална комуникация: Рендериране на текст
: Дизайн на икони
: Принципи на оформление
: Психология на цветовете
section Психология на играча (20 минути)
Системи за мотивация: Точки
: Риск срещу награда
: Обратна връзка за напредъка
: Дизайн на постиженията
section Техническа реализация (30 минути)
Владеене на Canvas: Позициониране на текст
: Рендериране на спрайтове
: Управление на състояния
: Оптимизация на производителността
section Баланс на играта (40 минути)
Дизайн на трудността: Управление на живота
: Криви на резултатите
: Задържане на играчите
: Достъпност
section Потребителски опит (50 минути)
Дизайн на интерфейса: Йерархия на информацията
: Отзивчива обратна връзка
: Емоционален дизайн
: Тестване на използваемостта
section Разширени системи (1 седмица)
Игрови механики: Системи за прогресия
: Интеграция на анализи
: Дизайн за монетизация
: Функции за общността
section Индустриални умения (1 месец)
Професионално развитие: Сътрудничество в екип
: Документация на дизайна
: Изследване на играчите
: Оптимизация на платформата
```
### 🛠️ Обзор на инструментите за дизайн на игри
След завършване на този урок вече сте овладели:
- **Психология на играча**: Разбиране на мотивацията, риск/награда и цикли на ангажираност
- **Визуална комуникация**: Ефективен дизайн на интерфейс с текст, икони и оформление
- **Системи за обратна връзка**: Отговор в реално време на действия и събития в играта
- **Управление на състоянието**: Ефикасно проследяване и показване на динамични данни
- **Рендиране на текст в канваса**: Професионално показване на текст със стилизиране и позициониране
- **Интеграция на събития**: Свързване на действията на потребителя със значими последици в играта
- **Баланс в играта**: Проектиране на криви на трудност и системи за прогрес на играча
**Приложения в реалния свят**: Вашите умения в дизайна на игри се прилагат директно в:
- **Дизайн на потребителски интерфейси**: Създаване на ангажиращи и лесни за използване интерфейси
- **Разработка на продукти**: Разбиране на мотивацията и циклите за обратна връзка на потребителите
- **Образователни технологии**: Геймификация и системи за ангажиране при учене
- **Визуализация на данни**: Правене на сложна информация достъпна и ангажираща
- **Разработка на мобилни приложения**: Механики за задържане и дизайн на потребителско изживяване
- **Маркетингови технологии**: Разбиране на поведението на потребителите и оптимизация на конверсията
**Професионални умения, придобити**: Вече можете:
- **Дизайн** на потребителски изживявания, които мотивират и ангажират
- **Прилагане** на системи за обратна връзка, които ефективно насочват поведението
- **Баланс** между предизвикателство и достъпност в интерактивни системи
- **Създаване** на визуална комуникация, работеща за различни групи потребители
- **Анализ** на поведението и итерации за подобрение на дизайна
**Овладени концепции в разработката на игри**:
- **Мотивация на играча**: Разбиране на това, което движи ангажираността и задържането
- **Визуален дизайн**: Създаване на ясни, атрактивни и функционални интерфейси
- **Интеграция на системи**: Свързване на множество игрови системи за цялостно преживяване
- **Оптимизация на производителността**: Ефикасно рендиране и управление на състоянието
- **Достъпност**: Проектиране за различни нива на умения и нужди на играчите
**Следващо ниво**: Готови сте да изследвате напреднали модели в дизайна на игри, да внедрявате аналитични системи или да изучавате монетизацията и задържането на играчи!
🌟 **Постижение отключено**: Изградихте пълна система за обратна връзка с играча, базирана на професионални принципи на гейм дизайна!
---
## Предизвикателство на GitHub Copilot Agent 🚀
## GitHub Copilot Agent Challenge 🚀
Използвайте режима Agent, за да завършите следното предизвикателство:
Използвайте режим Agent, за да изпълните следното предизвикателство:
**Описание:** Подобрете системата за точки в космическата игра, като внедрите функция за най-добър резултат с постоянна памет и механика за бонус точки.
**Описание:** Подобрете системата за точкуване на космическата игра, като реализирате система за най-висок резултат с постоянно съхранение и бонус система за последователни убийства.
**Задача:** Създайте система за най-добър резултат, която запазва най-добрия резултат на играча в localStorage. Добавете бонус точки за последователни унищожения на врагове (система за комбо) и внедрете различни стойности на точки за различни типове врагове. Включете визуален индикатор, когато играчът постигне нов най-добър резултат, и покажете текущия най-добър резултат на екрана на играта.
**Инструкция:** Създайте система за висок резултат, която запазва най-добрия резултат на играча в localStorage. Добавете бонус точки за поредни убийства на врагове (система за комбо) и реализирайте различни стойности за точки за различни типове врагове. Включете визуален индикатор при нов рекорд и показвайте текущия най-висок резултат на екрана на играта.
## 🚀 Предизвикателство
Вече имате функционална игра с точки и животи. Помислете какви допълнителни функции биха могли да подобрят изживяването на играча.
Вече имате функционална игра с точкови и животи. Помислете какви допълнителни функции биха подобрили изживяването на играча.
[Куиз след лекцията](https://ff-quizzes.netlify.app/web/quiz/38)
## Преглед и самостоятелно обучение
Искате ли да изследвате повече? Проучете различни подходи към системите за точки и животи в игрите. Съществуват интересни игрови двигатели като [PlayFab](https://playfab.com), които се занимават с точки, класации и прогресия на играчите. Как интегрирането на нещо подобно би могло да издигне вашата игра на следващото ниво?
Искате ли да изследвате повече? Разучете различни подходи към системите за точкуване и животи. Съществуват интересни игрови платформи като [PlayFab](https://playfab.com), които управляват точкуване, класации и прогрес на играчите. Как би повишило интегрирането на нещо такова нивото на вашата игра?
## Задача
[Създайте игра с точки](assignment.md)
[Изградете игра с точкуване](assignment.md)
---
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Отказ от отговорност**:
Този документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за каквито и да било недоразумения или погрешни интерпретации, произтичащи от използването на този превод.
Този документ е преведен с помощта на AI преводаческа услуга [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стараем за точност, моля, имайте предвид, че автоматизираните преводи могат да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за всякакви недоразумения или неправилни тълкувания, произтичащи от използването на този превод.
# Създаване на космическа игра, част 6: Край и рестарт
Всяка страхотна игра се нуждае от ясни условия за край и плавен механизъм за рестарт. Вече сте създали впечатляваща космическа игра с движение, битки и точки - сегае време да добавите последните елементи, които ще я направят завършена.
Вашата игра в момента продължава безкрайно, подобно на космическите сонди Voyager, които NASA изстреля през 1977 г. и които все още пътуват из космоса десетилетия по-късно. Докато това е подходящо за космическо изследване, игрите се нуждаят от определени крайни точки, за да създадат удовлетворяващо изживяване.
Днес ще внедрим правилни условия за победа/загуба и система за рестарт. До края на този урок ще имате завършена игра, която играчите могат да завършат и да играят отново, точно като класическите аркадни игри, които определиха жанра.
## Тест преди лекцията
# Създаване на космическа игра Част 6: Край и рестарт
```mermaid
journey
title Вашето пътешествие към завършване на играта
section Крайни условия
Определяне на състояния за победа/загуба: 3: Student
Изпълнение на проверка на условия: 4: Student
Обработка на преходи между състояния: 4: Student
section Игрово изживяване
Проектиране на системи за обратна връзка: 4: Student
Създаване на механика за рестартиране: 5: Student
Полиране на потребителския интерфейс: 5: Student
section Интеграция на системата
Управление на жизнения цикъл на играта: 5: Student
Обработка на почистване на паметта: 5: Student
Създаване на пълно изживяване: 5: Student
```
Всяка страхотна игра се нуждае от ясни условия за край и гладък механизъм за рестартиране. Вие създадохте впечатляваща космическа игра с движение, бой и точки - сегае време да добавите последните елементи, които я правят завършена.
Вашата игра в момента работи безкрайно, като сондажите Voyager, които НАСА пусна през 1977 г. - все още пътуващи в космоса десетилетия по-късно. Докато това е добре за космически изследвания, игрите се нуждаят от дефинирани крайни точки, за да създадат удовлетворяващи преживявания.
Днес ще имплементираме правилни условия за победа/загуба и система за рестартиране. В края на този урок ще имате полирана игра, която играчите могат да завършат и да играят отново, точно като класическите аркадни игри, които определиха жанра.
```mermaid
mindmap
root((Завършване на игра))
End Conditions
Victory States
Defeat Conditions
Progress Tracking
State Validation
Player Feedback
Visual Messages
Color Psychology
Clear Communication
Emotional Response
State Management
Game Loop Control
Memory Cleanup
Object Lifecycle
Event Handling
Restart Systems
Input Handling
State Reset
Fresh Initialization
User Experience
Polish Elements
Message Display
Smooth Transitions
Error Prevention
Accessibility
```
## Куиз преди лекцията
[Тест преди лекцията](https://ff-quizzes.netlify.app/web/quiz/39)
[Куиз преди лекцията](https://ff-quizzes.netlify.app/web/quiz/39)
## Разбиране на условията за край на играта
Кога трябва да приключи вашата игра? Този фундаментален въпрос е оформял дизайна на игрите още от ранната аркадна ера. Pac-Man приключва, когато бъдете хванати от призраци или изчистите всички точки, докато Space Invaders приключва, когато извънземните достигнат дъното или когато ги унищожите всички.
Като създател на играта, вие определяте условията за победа и загуба. За нашата космическа игра, ето доказани подходи, които създават увлекателен геймплей:
- **Унищожени `N` вражески кораба**: Често срещано е, ако разделите играта на различни нива, да трябва да унищожите `N` вражески кораба, за да завършите нивото.
- **Вашият кораб е унищожен**: Има игри, в които губите, ако вашият кораб бъде унищожен. Друг често срещан подход е концепцията за животи. Всеки път, когато вашият кораб бъде унищожен, се отнема един живот. Когато всички животи бъдат загубени, играта приключва.
- **Събрани са`N` точки**: Друго често срещано условие за край е събирането на точки. Как ще събирате точки зависи от вас, но често се присъждат точки за различни дейности като унищожаване на вражески кораб или събиране на предмети, които падат, когато те бъдат унищожени.
- **Завършване на ниво**: Това може да включва няколко условия, като унищожени `X` вражески кораба, събрани `Y` точки или може би събиране на конкретен предмет.
## Внедряване на функционалност за рестарт на играта
Добрите игри насърчават повторяемостта чрез плавни механизми за рестарт. Когато играчите завършат играта (или претърпят поражение), те често искат веднага да опитат отново - било то за да подобрят резултата си или представянето си.
Tetris е перфектен пример за това: когато блоковете достигнат върха, можете веднага да започнете нова игра, без да се налага да навигирате през сложни менюта. Ще изградим подобна система за рестарт, която чисто ще нулира състоянието на играта и ще върне играчите обратно в действие бързо.
Кога трябва да свърши играта ви? Този основен въпрос определя дизайна на игрите още от ранната аркадна ера. Pac-Man свършва, когато бъдете хванати от призраци или изчистите всички точки, докато Space Invaders свършва, когато извънземните достигнат дъното или бъдат унищожени всички.
Като създател на играта, вие определяте условията за победа и загуба. За нашата космическа игра ето доказани подходи, които създават завладяващ геймплей:
```mermaid
flowchart TD
A["🎮 Старт на играта"] --> B{"Провери условията"}
B --> C["Брой врагове"]
B --> D["Животи на героя"]
B --> E["Праг на резултата"]
B --> F["Напредък на ниво"]
C --> C1{"Враговете = 0?"}
D --> D1{"Животите = 0?"}
E --> E1{"Резултатът ≥ Целта?"}
F --> F1{"Целите са изпълнени?"}
C1 -->|Да| G["🏆 Победа"]
D1 -->|Да| H["💀 Загуба"]
E1 -->|Да| G
F1 -->|Да| G
C1 -->|Не| B
D1 -->|Не| B
E1 -->|Не| B
F1 -->|Не| B
G --> I["🔄 Опция за рестарт"]
H --> I
style G fill:#e8f5e8
style H fill:#ffebee
style I fill:#e3f2fd
```
- **Унищожени са`N` вражески кораба**: Често се случва при разделяне на играта на нива да трябва да унищожите `N` вражески кораба, за да завършите едно ниво
- **Вашият кораб е унищожен**: Определено има игри, при които губите, ако корабът ви бъде унищожен. Друг често срещан подход е понятието за животи. Всеки път, когато корабът ви бъде унищожен, се губи един живот. След като всички животи са изчерпани, губите играта.
- **Събрани са`N` точки**: Друго често условие за край е събирането на точки. Как събирате точки зависи от вас, но обичайно точките се връзват с различни дейности като унищожаване на вражески кораб или събиране на предмети, които *падат* при унищожаване.
- **Завършване на ниво**: Това може да включва няколко условия като унищожаване на `X` вражески кораба, събиране на `Y` точки или пък събиране на конкретен артикул.
## Имплементиране на функция за рестарт на играта
Добре направените игри насърчават възможността за многократно играене чрез гладки механизми за рестартиране. Когато играчите завършат играта (или загубят), те често искат да опитат отново веднага — за да подобрят резултата си или изпълнението.
```mermaid
stateDiagram-v2
[*] --> Playing: Старт на играта
Playing --> Victory: Всички врагове са унищожени
Playing --> Defeat: Животи = 0
Victory --> MessageDisplay: Покажи съобщение за победа
Defeat --> MessageDisplay: Покажи съобщение за загуба
MessageDisplay --> WaitingRestart: Подканва за натискане на Enter
WaitingRestart --> Resetting: Натиснат Enter
Resetting --> CleanupMemory: Изчистване на интервали
CleanupMemory --> ClearEvents: Премахване на слушатели
ClearEvents --> InitializeGame: Нов старт
InitializeGame --> Playing: Започва нова игра
note right of MessageDisplay
Цветно кодирана обратна връзка:
Зелено = Победа
Червено = Загуба
end note
note right of Resetting
Пълно нулиране на състоянието
предотвратява изтичане на памет
end note
```
Tetris е отличен пример: когато блоковете достигнат върха, може веднага да започнете нова игра без да навигирате през сложни менюта. Ние ще създадем подобна система за рестарт, която изчиства състоянието на играта и връща играчите бързо в действие.
✅ **Размисъл**: Помислете за игрите, които сте играли. При какви условия те приключват и как ви подканват да рестартирате? Какво прави изживяването при рестарт гладко, а не разочароващо?
✅ **Рефлексия**: Помислете за игрите, които сте играли. При какви условия свършват и как ви подканват да рестартирате? Какво прави преживяването при рестарт гладко или разочароващо?
## Какво ще изградите
## Какво ще създадете
Ще внедрите финалните функции, които ще превърнат вашия проект в завършено игрово изживяване. Тези елементи отличават полирани игри от основни прототипи.
Ще имплементирате последните функции, които превръщат проекта ви в завършено игрово преживяване. Тези елементи отличават полирани игри от базови прототипи.
**Ето какво ще добавим днес:**
**Ето какво добавяме днес:**
1. **Условие за победа**: Унищожете всички врагове и получете подходящо празненство (заслужавате го!)
2. **Условие за загуба**: Загубете всички животи и се изправете пред поражението с екран за загуба
3. **Механизъм за рестарт**: Натиснете Enter, за да се върнете веднага - защото една игра никога не е достатъчна
4. **Управление на състоянието**: Чисто начало всеки път - без остатъчни врагове или странни грешки от предишната игра
1. **Условие за победа**: Унищожете всички врагове и получете подобаващо отбелязване (вие го заслужихте!)
2. **Условие за загуба**: Изчерпайте всички животи и се сбогувайтес екран за загуба
3. **Механизъм за рестартиране**: Натиснете Enter, за да влезете отново - защото една игра никога не е достатъчна
4. **Управление на състоянието**: Винаги чисто - няма останали врагове или странни бъгове от предишната игра
## Да започваме
## Започваме
Нека подготвим вашата среда за разработка. Трябва да имате всички файлове на вашата космическа игра от предишните уроци.
Нека подготвим вашата среда за разработка. Трябва да имате всички файлове на космическата си игра от предишните уроци.
**Вашият проект трябва да изглежда приблизително така:**
@ -75,18 +179,43 @@ npm start
**Тази команда:**
- Стартира локален сървър на `http://localhost:5000`
- Правилно обслужва вашите файлове
- Автоматично се обновява, когато правите промени
Отворете `http://localhost:5000` в браузъра си и проверете дали играта ви работи. Трябва да можете да се движите, стреляте и взаимодействате с враговете. След като потвърдите, можем да продължим с внедряването.
> 💡 **Полезен съвет**: За да избегнете предупреждения в Visual Studio Code, декларирайте `gameLoopId` в началото на вашия файл като `let gameLoopId;` вместо да го декларирате вътре във функцията `window.onload`. Това следва съвременните най-добри практики за деклариране на променливи в JavaScript.
## Стъпки за внедряване
- Сервира вашите файлове правилно
- Автоматично обновява страницата при направени промени
Отворете `http://localhost:5000` в браузъра и уверете се, че играта работи. Трябва да може да се движите, стреляте и взаимодействате с враговете. След като потвърдите, можем да продължим с имплементацията.
> 💡 **Полезен съвет**: За да избегнете предупреждения във Visual Studio Code, декларирайте `gameLoopId` в началото на файла като `let gameLoopId;` вместо да го обявявате във функцията `window.onload`. Това следва добрите практики за деклариране на променливи в съвременния JavaScript.
```mermaid
flowchart TD
A["1. Следене на условието"] --> B["2. Обработчици на събития"]
B --> C["3. Константи на съобщения"]
C --> D["4. Контроли за рестартиране"]
D --> E["5. Показване на съобщения"]
E --> F["6. Рестартиране на системата"]
G["isHeroDead()\nisEnemiesDead()"] --> A
H["Събития при сблъсък\nСъбития за край на играта"] --> B
I["GAME_END_WIN\nGAME_END_LOSS"] --> C
J["Входен клавиш\nТригър за рестарт"] --> D
K["Победа/Загуба\nТекст с цветово кодиране"] --> E
L["Почистване на състоянието\nСвежо инициализиране"] --> F
F --> M["🎮 Пълна игра"]
style A fill:#e3f2fd
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#f3e5f5
style E fill:#e0f2f1
style F fill:#fce4ec
style M fill:#e1f5fe
```
## Стъпки за имплементация
### Стъпка 1: Създаване на функции за проследяване на условията за край
### Стъпка 1: Създаване на функции за следене на крайни условия
Трябва да създадем функции, които да следят кога играта трябва да приключи. Подобно на сензорите на Международната космическа станция, които постоянно следят критичните системи, тези функции ще проверяват състоянието на играта.
Имаме нужда от функции, които да следят кога играта трябва да свърши. Както сензори на Международната космическа станция постоянно наблюдават критични системи, тези функции непрекъснато ще проверяват състоянието на играта.
```javascript
function isHeroDead() {
@ -99,17 +228,50 @@ function isEnemiesDead() {
}
```
**Ето какво се случва зад кулисите:**
- **Проверява** дали нашият герой е загубил всички животи (ау!)
- **Брои** колко врагове все още са живи и активни
- **Връща** `true`, когато бойното поле е изчистено от врагове
- **Използва** проста логика true/false за по-лесно разбиране
- **Филтрира** всички игрови обекти, за да намери оцелелите
### Стъпка 2: Актуализиране на обработката на събития за условията за край
Сега ще свържем тези проверки на условията с системата за събития на играта. Всеки път, когато се случи сблъсък, играта ще оцени дали той предизвиква условие за край. Това създава незабавна обратна връзка за критични събития в играта.
**Ето какво се случва под капака:**
- **Проверява** дали нашият герой е без животи (айде!)
- **Брои** колко врагове са още живи и активни
- **Връща** `true`, когато бойното поле е чисто от врагове
- **Използва** проста логика true/false за по-лесен контрол
- **Филтрира** всички обекти в играта, за да намери оцелелите
### Стъпка 2: Актуализиране на обработващите събития според крайни условия
Сега ще свържем тези проверки с системата за събития на играта. Всеки път, когато настъпи сблъсък, играта ще преценява дали това предизвиква крайно условие. Това създава мигновена обратна връзка при критични моменти.
```mermaid
sequenceDiagram
participant Collision
participant GameLogic
participant Conditions
participant EventSystem
participant Display
Collision->>GameLogic: Лазер удря враг
GameLogic->>GameLogic: Унищожаване на обекти
GameLogic->>Conditions: Проверка isEnemiesDead()
alt Всички врагове победени
Conditions->>EventSystem: Изпращане на GAME_END_WIN
EventSystem->>Display: Покажи съобщение за победа
else Врагове остават
Conditions->>GameLogic: Продължаване на играта
end
Collision->>GameLogic: Враг удря героя
GameLogic->>GameLogic: Намаляване на животи
GameLogic->>Conditions: Проверка isHeroDead()
alt Животи = 0
Conditions->>EventSystem: Изпращане на GAME_END_LOSS
EventSystem->>Display: Покажи съобщение за загуба
else Животи остават
GameLogic->>Conditions: Проверка isEnemiesDead()
alt Всички врагове победени
Conditions->>EventSystem: Изпращане на GAME_END_WIN
end
end
```
```javascript
eventEmitter.on(Messages.COLLISION_ENEMY_LASER, (_, { first, second }) => {
- **Лазер удря враг**: И двамата изчезват, получавате точки и проверяваме дали сте спечелили
- **Враг удря вас**: Губите живот и проверяваме дали все още сте "живи"
- **Умно подреждане**: Първо проверяваме за поражение (никой не иска да спечели и да загуби едновременно!)
- **Моментални реакции**: Веднага щом се случи нещо важно, играта го отчита
**Какво става тук:**
- **Лъчът удря враг**: И двамата изчезват, вие получавате точки и проверяваме дали сте спечелили
- **Враг удря вас**: Губите живот и проверяваме дали все още сте жив
- **Умно подреждане**: Най-напред проверяваме загуба (никой не иска да печели и губи едновременно!)
- **Мигновена реакция**: Веднага щом нещо важно се случи, играта го знае
### Стъпка 3: Добавяне на нови константи за съобщения
Трябва да добавите нови типове съобщения към вашия обект `Messages`. Тези константи помагат за поддържане на последователност и предотвратяване на грешки в системата за събития.
Ще трябва да добавите нови типове съобщения към константния обект `Messages`. Тези константи помагат да се поддържа консистентност и да се избягват грешки при писане в системата за събития.
```javascript
GAME_END_LOSS: "GAME_END_LOSS",
GAME_END_WIN: "GAME_END_WIN",
```
**В горното сме:**
- **Добавили** константи за събития, свързани с края на играта, за да поддържаме последователност
- **Използвали** описателни имена, които ясно указват целта на събитието
- **Следвали** съществуващата конвенция за именуване на типове съобщения
**В горното добавихме:**
- **Константи** за крайни събития в играта за поддържане на последователност
- **Описателни имена**, които ясно показват целта на събитието
- **Следвахме** съществуващата конвенция за именуване на типове съобщения
### Стъпка 4: Внедряване на контроли за рестарт
### Стъпка 4: Имплементиране на контролите за рестарт
Сега ще добавите клавишни контроли, които позволяват на играчите да рестартират играта. Клавишът Enter е естествен избор, тъй като обикновено се свързва с потвърждаване на действия и стартиране на нови игри.
Сега ще добавите клавиатурни контроли, позволяващи на играчите да рестартират играта. Клавиш Enter е естествен избор, тъй като е широко свързан с потвърждаване на действия и започване на нови игри.
**Добавете разпознаване на клавиша Enter към съществуващия слушател на събития за натискане на клавиши:**
**Добавете разпознаване на клавиша Enter към съществуващия слушател за `keydown`:**
- **Разширява** съществуващата система за обработка на събития от клавиатурата
- **Използва** клавиша Enter като тригер за рестарт за интуитивно потребителско изживяване
- **Излъчва** персонализирано събитие, което други части на играта могат да слушат
- **Поддържа** същия модел като другите клавишни контроли
**Това, което трябва да знаете:**
- **Разширява** съществуващата система за обработка на клавиатурни събития
- **Използва** клавиша Enter като активатор за рестарт за интуитивно преживяване
- **Изпраща** персонализирано събитие, което други части от играта могат да слушат
- **Поддържа** същия модел като другите клавиатурни контроли
### Стъпка 5: Създаване на система за показване на съобщения
Вашата игра трябва ясно да комуникира резултатите на играчите. Ще създадем система за съобщения, която показва състоянията на победа и загуба с цветно кодирани текстове, подобно на интерфейсите на терминалите на ранните компютърни системи, където зелено означава успех, а червено сигнализира за грешки.
Играта ви трябва ясно да комуникира резултатите на играча. Ще създадем система за съобщения, която показва състоянията за победа и загуба с цветен текст, подобно на терминалните интерфейси на ранните компютърни системи, където зелено означава успех, а червено предупреждение.
**Създайте функцията `displayMessage()`:**
@ -202,11 +364,11 @@ function displayMessage(message, color = "red") {
```
**Стъпка по стъпка, ето какво се случва:**
- **Задава** размера и стила на шрифта за ясен и четлив текст
- **Прилага** цветен параметър с "червено" като стандартен за предупреждения
- **Центрира** текста хоризонтално и вертикално върху платното
- **Използва** съвременни JavaScript параметри по подразбиране за гъвкави цветови опции
- **Използва** 2D контекста на платното за директно рендиране на текст
- **Настройва** размер на шрифта и семейство за ясен и четим текст
- **Прилага** параметър за цвят с "червено" по подразбиране за предупреждения
- **Центрира** текста по хоризонтала и вертикала на канваса
- **Използва** съвременни параметри по подразбиране в JavaScript за гъвкавост
- **Употребява** 2D контекста на канваса за директно рендиране на текста
**Създайте функцията `endGame()`:**
@ -214,7 +376,7 @@ function displayMessage(message, color = "red") {
function endGame(win) {
clearInterval(gameLoopId);
// Set a delay to ensure any pending renders complete
// Задайте забавяне, за да се уверите, че всички чакащи рендери са завършени
setTimeout(() => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "black";
@ -234,16 +396,32 @@ function endGame(win) {
```
**Какво прави тази функция:**
- **Замразява** всичко на място - край на движението на кораби и лазери
- **Прави** малка пауза (200ms), за да позволи на последния кадър да се нарисува
- **Замразява** всичко - няма повече движение на кораби или лазери
- **Прави** кратка пауза (200 ms), за да завърши последният кадър
- **Изчиства** екрана и го боядисва в черно за драматичен ефект
- **Показва** различни съобщения за победители и губещи
- **Кодира** новините с цветове - зелено за добро, червено за... е, не толкова добро
- **Уведомява** играчите как да се върнат в играта
- **Показва** различни съобщения за победители и загубили
- **Кодира цвета** - зелено за добро, червено за... не толкова добро
- **Казва** на играчите как да рестартират
### 🔄 **Образователна проверка**
**Управление на състоянието на играта**: Преди да имплементирате функционалността за рестарт, уверете се, че разбирате:
- ✅ Как крайните условия създават ясни цели за геймплея
- ✅ Защо визуалната обратна връзка е съществена за разбирането на играча
- ✅ Важността на правилното почистване за предотвратяване на изтичане на памет
- ✅ Как архитектурата, базирана на събития, позволява чисти преходи в състоянието
**Бърз самотест**: Какво би се случило, ако не изчистите слушателите на събития при рестарт?
*Отговор: Изтичане на памет и дублирани обработващи, които причиняват непредвидимо поведение*
**Принципи на гейм дизайна**: Вие сега внедрявате:
- **Ясни цели**: Играчите знаят точно какво означава успех и провал
- **Мигновена обратна връзка**: Промяната в състоянието е комуникирана веднага
- **Контрол от страна на потребителя**: Играчите могат да рестартират, когато решат
- **Надеждност на системата**: Правилното почистване предотвратява бъгове и проблеми с производителността
### Стъпка 6: Внедряване на функционалност за рестарт на играта
### Стъпка 6: Имплементиране на функционалност за рестарт
Системата за рестарт трябва напълно да изчисти текущото състояние на играта и да инициализира нова игрова сесия. Това гарантира, че играчите започват начисто, без остатъчни данни от предишната игра.
Системата за рестарт трябва напълно да изчисти текущото състояние на играта и да инициализира нова сесия. Това гарантира, че играчите започват отначало без остатъчни данни от предишната игра.
**Създайте функцията `resetGame()`:**
@ -267,14 +445,14 @@ function resetGame() {
```
**Нека разберем всяка част:**
- **Проверява** дали текущо работи игрови цикъл, преди да го рестартира
- **Изчиства** съществуващия игрови цикъл, за да спре текущата игрова активност
- **Премахва** всички слушатели на събития, за да предотврати изтичане на памет
- **Реинициализира** състоянието на играта с нови обекти и променливи
- **Стартира** нов игрови цикъл с всички основни функции на играта
- **Поддържа** същия интервал от 100ms за последователна производителност на играта
- **Проверява** дали в момента работи игрови цикъл преди рестарт
- **Изчиства** съществуващия цикъл, за да спре текущата игра
- **Премахва** всички слушатели на събития за предотвратяване на изтичане на памет
- **Инициализира** ново състояние на играта с пресни обекти и променливи
- **Стартира** нов игрови цикъл с всички основни функции
- **Поддържа** същия интервал от 100 ms за стабилна производителност
**Добавете обработка на събитие за клавиша Enter към вашата функция`initGame()`:**
**Добавете обработчик за клавиша Enter във функцията`initGame()`:**
**Добавете метода `clear()` към вашия клас EventEmitter:**
**Добавете метода `clear()` към класа EventEmitter:**
```javascript
clear() {
@ -290,67 +468,217 @@ clear() {
}
```
**Основни точки за запомняне:**
- **Свързва** натискането на клавиша Enter с функционалността за рестарт на играта
- **Регистрира** този слушател на събития по време на инициализацията на играта
- **Осигурява** чист начин за премахване на всички слушатели на събития при рестарт
- **Предотвратява** изтичане на памет чрез изчистване на обработчиците на събития между игрите
- **Нулира** обекта listeners до празно състояние за нова инициализация
**Основни моменти за запомняне:**
- **Свързва** натискането на Enter с функцията за рестарт на играта
- **Регистрира** слушателя по време на инициализация на играта
- **Предоставя** чист начин за премахване на всички слушатели при рестарт
- **Предотвратява** изтичане на памет чрез изчистване на обработващите събития между игрите
- **Рестартира** обекта с слушатели до празно състояние за ново начало
## Поздравления! 🎉
👽 💥 🚀 Успешно създадохте завършена игра от нулата. Както програмистите, които създадоха първите видеоигри през 70-те години, вие превърнахте редове код в интерактивно изживяване с правилни игрови механики и обратна връзка към потребителя. 🚀 💥 👽
👽 💥 🚀 Вие успешно създадохте цяла игра от основата до край. Подобно на програмистите, създали първите видео игри през 70-те, превърнахте редове код в интерактивно преживяване със задължителна гейм механика и обратна връзка към потребителя. 🚀 💥 👽
**Постигнахте:**
- **Внедрихте** пълни условия за победа и загуба с обратна връзка към потребителя
- **Създадохте** плавна система за рестарт за непрекъснат геймплей
- **Проектирахте** ясна визуална комуникация за състоянията на играта
- **Управлявахте** сложни преходи на състоянието на играта и изчистване
- **Сглобихте** всички компоненти в един цялостен, играем проект
- **Имплементирахте** пълни условия за победа и загуба с обратна връзка към играча
- **Създадохте** безпроблемна система за рестарт за непрекъснат геймплей
- **Дизайнирахте** ясна визуална комуникация за състоянията на играта
- **Управлявахте** сложни преходи на състоянието и почистването му
- **Събрахте** всички компоненти в една цялостна, играбилна игра
### 🔄 **Образователна проверка**
**Пълна система за разработка на игри**: Поздравете се за овладяването на целия цикъл на разработка:
- ✅ Как крайните условия създават удовлетворяващи преживявания за играчите?
- ✅ Защо правилното управление на състоянието е критично за стабилността на играта?
- ✅ Как визуалната обратна връзка подобрява разбирането на играча?
- ✅ Каква роля играе системата за рестарт в задържането на играчите?
**Майсторство на системата**: Вашата пълна игра демонстрира:
- **Разработка на игри с пълна технология**: От графики и входове до управление на състоянието
- **Професионална архитектура**: Система, базирана на събития със съответното почистване
- **Дизайн на потребителско изживяване**: Ясна обратна връзка и интуитивно управление
- **Оптимизация на производителността**: Ефикасно рендиране и управление на паметта
- **Полиране и завършеност**: Всички детайли, които правят играта да изглежда готова
**Умения за индустрията**: Вие имплементирахте:
- **Архитектура на игров цикъл**: Системи в реално време с постоянна производителност
- **Програмиране, базирано на събития**: Свързани системи с лесно разширение
- **Управление на състоянието**: Обработка на сложни данни и жизнен цикъл
- **Дизайн на интерфейс**: Ясна комуникация и отзивчиви контроли
- **Тестване и отстраняване на грешки**: Итеративна разработка и решаване на проблеми
### ⚡ **Какво можете да направите през следващите 5 минути**
- [ ] Играйте вашата завършена игра и тествайте всички условия за победа и загуба
- [ ] Експериментирайте с различни параметри на крайните условия
- [ ] Опитайте да добавите console.log изказвания за проследяване на състоянието на играта
- [ ] Споделете играта с приятели и съберете обратна връзка
### 🎯 **Какво можете да постигнете този час**
- [ ] Завършете куиза след урока и размишлявайте върху пътя си в разработката на игри
- [ ] Добавете звукови ефекти за състояния победа и загуба
- [ ] Имплементирайте допълнителни крайни условия като времеви ограничения или бонус цели
- [ ] Създайте различни нива на трудност с променлив брой врагове
- [ ] Полирайте визуалната презентация с по-добри шрифтове и цветове
### 📅 **Вашето седмично овладяване на разработка на игри**
- [ ] Завършете подобрената космическа игра с множество нива и прогресия
- [ ] Добавете разширени функции като усилватели, различни видове врагове и специално оръжие
- [ ] Създайте система за високи резултати с постоянно съхранение
- [ ] Дизайнирайте потребителски интерфейси за менюта, настройки и опции на играта
- [ ] Оптимизирайте производителността за различни устройства и браузъри
- [ ] Публикувайте играта онлайн и я споделете с общността
### 🌟 **Вашата месечна кариера в разработката на игри**
- [ ] Създайте няколко пълни игри, изследвайки различни жанрове и механики
- [ ] Научете се на усъвършенствани рамки за разработка на игри като Phaser или Three.js
- [ ] Допринасяйте за отворени проекти за разработка на игри
- [ ] Изучавайте принципите на гейм дизайна и психологията на играчите
- [ ] Създайте портфолио, което показва вашите умения в разработката на игри
- [ ] Свържете сес общността на разработчиците на игри и продължавайте да учите
## 🎯 Вашата пълна времева линия за овладяване на разработката на игри
```mermaid
timeline
title Пълно обучение за разработка на игри
section Основи (Уроци 1-2)
Game Architecture: Структура на проекта
: Управление на ресурси
: Основи на канвас
: Системи за събития
section Системи за взаимодействие (Уроци 3-4)
Player Control: Обработка на входящи данни
: Механика на движение
: Откриване на сблъсъци
: Симулиране на физика
section Механики на играта (Урок 5)
Feedback Systems: Механизми за оценяване
: Управление на живот
: Визуална комуникация
: Мотивация на играча
section Завършване на играта (Урок 6)
Polish & Flow: Краен статус
: Управление на състояния
: Системи за рестартиране
: Потребителски опит
section Разширени функции (1 седмица)
Enhancement Skills: Интеграция на аудио
: Визуални ефекти
: Прогресия на нива
: Оптимизация на производителността
section Професионално развитие (1 месец)
Industry Readiness: Майсторство на рамки
: Сътрудничество в екип
: Развитие на портфолио
: Взаимодействие с общността
section Кариерен напредък (3 месеца)
Specialization: Разширени игрови двигатели
: Публикуване на платформи
: Стратегии за монетизация
: Мрежи в индустрията
```
### 🛠️ Обобщение на пълния ви набор от инструменти за разработка на игри
След като завършихте целия този космически игрови сериал, вече сте овладяли:
- **Архитектура на игрите**: Системи, базирани на събития, игрови цикли и управление на състояния
- **Графично програмиране**: Canvas API, рендиране на спрайтове и визуални ефекти
- **Системи за въвеждане**: Обработка на клавиатура, откриване на сблъсъци и отзивчиви контроли
- **Гейм дизайн**: Обратна връзка от играчите, системи за прогресия и механики за ангажиране
- **Оптимизация на производителността**: Ефективно рендиране, управление на паметта и контрол на кадрите в секунда
- **Потребителски опит**: Ясна комуникация, интуитивни контроли и детайли на полиране
- **Професионални модели**: Чист код, техники за отстраняване на грешки и организиране на проекти
**Приложения в реалния свят**: Вашите умения за разработка на игри се прилагат директно към:
- **Интерактивни уеб приложения**: Динамични интерфейси и системи в реално време
- **Визуализация на данни**: Анимирани графики и интерактивни визуализации
- **Образователни технологии**: Геймификация и ангажиращи учебни преживявания
- **Мобилна разработка**: Взаимодействия на базата на докосване и оптимизация на производителността
- **Симулативен софтуер**: Физически енджини и моделиране в реално време
- **Креативни индустрии**: Интерактивно изкуство, забавление и дигитални преживявания
**Професионални умения, придобити**: Сега можете да:
- **Архитектиране** на сложни интерактивни системи от нулата
- **Отстраняване на грешки** в приложения в реално време чрез систематични подходи
- **Оптимизиране** на производителността за плавно потребителско преживяване
- **Дизайн** на ангажиращи потребителски интерфейси и модели на взаимодействие
- **Сътрудничество** ефективно по технически проекти с правилна организация на кода
**Овладени концепции в разработката на игри**:
- **Системи в реално време**: Игрови цикли, управление на кадрите и производителност
- **Архитектура, базирана на събития**: Отделени системи и предаване на съобщения
- **Управление на състоянията**: Сложно обработване на данни и управление на жизнения цикъл
- **Програмиране на потребителския интерфейс**: Canvas графики и адаптивен дизайн
- **Теория на гейм дизайна**: Психология на играча и механики на ангажиране
## Предизвикателство с GitHub Copilot Agent 🚀
**Следващо ниво**: Готови сте да изследвате усъвършенствани рамки за игри, 3D графики, мултиплейър системи или да преминете към професионална разработка на игри!
Използвайте режима Agent, за да завършите следното предизвикателство:
🌟 **Постижение отключено**: Завършихте пълно игрово пътешествие и създадохте професионално интерактивно преживяване от нулата!
**Описание:** Подобрете космическата игра, като внедрите система за прогресия на нивата с увеличаваща се трудност и бонус функции.
**Добре дошли в общността на разработчиците на игри!** 🎮✨
**Задача:** Създайте система за многоневова космическа игра, в която всяко ниво има повече вражески кораби с увеличена скорост и здраве. Добавете множител за точки, който се увеличава с всяко ниво, и внедрете бонуси (като бърза стрелба или щит), които се появяват случайно, когато враговете бъдат унищожени. Включете бонус за завършване на ниво и показвайте текущото ниво на екрана заедно със съществуващите точки и животи.
## Предизвикателство за GitHub Copilot Agent 🚀
Научете повече за [режим Agent](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
Използвайте режим Agent, за да изпълните следното предизвикателство:
**Описание:** Подобрете космическата игра, като въведете система за прогресия на нива с нарастваща трудност и бонус функции.
**Тема:** Създайте система за космическа игра с няколко нива, където всяко ниво има повече вражески кораби с увеличена скорост и здравина. Добавете множител на точките, който се увеличава с всяко ниво, и имплементирайте бонуси (като бърз огън или щит), които се появяват случайно при унищожаване на врагове. Включете бонус за завършване на ниво и показвайте текущото ниво на екрана заедно със съществуващия резултат и животи.
Научете повече за [agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
## 🚀 Допълнително предизвикателство за подобрение
**Добавете аудио към вашата игра**: Подобрете игровото изживяване, като внедрите звукови ефекти! Помислете за добавяне на аудио за:
**Добавете звук към играта си**: Подобрете геймплея, като добавите звукови ефекти! Помислете за добавяне на аудио за:
- **Лазерни изстрели**, когато играчът стреля
- **Унищожаване на врагове**, когато корабите бъдат ударени
- **Унищожаване на враг** при удари по кораби
- **Щети на героя**, когато играчът получава удари
- **Победна музика**, когато играта е спечелена
- **Звук за поражение**, когато играта е загубена
- **Музика за победа**, когато играта е спечелена
- **Звук за загуба**, когато играта е загубена
**Пример за внедряване на аудио:**
**Пример за реализиране на аудио:**
```javascript
// Create audio objects
// Създаване на аудио обекти
const laserSound = new Audio('assets/laser.wav');
const explosionSound = new Audio('assets/explosion.wav');
// Play sounds during game events
// Възпроизвеждане на звуци по време на игрови събития
function playLaserSound() {
laserSound.currentTime = 0; // Reset to beginning
laserSound.currentTime = 0; // Рестартиране в началото
laserSound.play();
}
```
**Какво трябва да знаете:**
- **Създава** аудио обекти за различни звукови ефекти
- **Нулира** `currentTime`, за да позволи бързо възпроизвеждане на звукови ефекти
- **Обработва** политики за автоматично възпроизвеждане на браузъра, като задейства звуци от взаимодействия на потребителя
- **Управлява** силата на звука и времето за по-добро игрово изживяване
- **Създава** Audio обекти за различни звукови ефекти
- **Ресетва** `currentTime`, за да позволи бързи повторни звуци
- **Управлява** политики за автоматично пускане на звуци чрез задействане от потребителски действия
- **Контролира** звука и времето за по-добро игрово преживяване
> 💡 **Учебен ресурс**: Разгледайте този [audio sandbox](https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_audio_play), за да научите повече за имплементирането на аудио в JavaScript игри.
## Куиз след лекцията
[Куиз след лекцията](https://ff-quizzes.netlify.app/web/quiz/40)
## Преглед и самостоятелно обучение
Вашата задача е да създадете нова примерна игра, така че разгледайте някои от интересните игри, налични там, за да видите какъв тип игра бихте могли да направите.
## Задание
> 💡 **Ресурс за обучение**: Разгледайте този [аудио пясъчник](https://www.w3
[Създайте примерна игра](assignment.md)
---
**Отказ от отговорност**:
Този документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Не носим отговорност за недоразумения или погрешни интерпретации, произтичащи от използването на този превод.
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Отказ от отговорност**:
Този документ е преведен с помощта на AI преводаческа услуга [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматичните преводи могат да съдържат грешки или неточности. Оригиналният документ на неговия оригинален език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Не носим отговорност за каквито и да е недоразумения или неправилни тълкувания, произтичащи от използването на този превод.
# Създаване на банково приложение, част 1: HTML шаблони и маршрути в уеб приложение
# Създаване на банково приложение Част 1: HTML шаблони и маршрути в уеб приложение
Когато компютърът за управление на Apollo 11 навигираше към Луната през 1969 г., той трябваше да превключва между различни програми, без да рестартира цялата система. Съвременните уеб приложения работят по подобен начин – те променят това, което виждате, без да презареждат всичко отначало. Това създава гладко и отзивчиво изживяване, което потребителите очакват днес.
```mermaid
journey
title Вашето пътуване в разработката на банкова приложение
section Основи на SPA
Разберете едностранични приложения: 3: Student
Научете концепциите за шаблони: 4: Student
Овладейте манипулацията на DOM: 4: Student
section Системи за маршрутизация
Изпълнете маршрутизация от страна на клиента: 4: Student
Управлявайте историята на браузъра: 5: Student
Създайте навигационни системи: 5: Student
section Професионални модели
Изградете модулна архитектура: 5: Student
Прилагайте най-добри практики: 5: Student
Създайте потребителски преживявания: 5: Student
```
Когато навигационният компютър на Apollo 11 стигна до Луната през 1969 г., той трябваше да превключва между различни програми без да рестартира цялата система. Модерните уеб приложения работят по подобен начин – те променят това, което виждате, без да презареждат всичко отначало. Това създава гладко и отзивчиво изживяване, което потребителите очакват днес.
За разлика от традиционните уебсайтове, които презареждат цели страници при всяко взаимодействие, модерните уеб приложения актуализират само частите, които се нуждаят от промяна. Този подход, подобно на начина, по който контролният център превключва между различни дисплеи, като същевременно поддържа постоянна комуникация, създава плавното изживяване, което сме свикнали да очакваме.
За разлика от традиционните уебсайтове, които презареждат цели страници при всяко взаимодействие, модерните уеб приложения обновяват само необходимите части. Този подход, подобно на това как командният център превключва между различни дисплеи, като същевременно поддържа постоянна комуникация, създава плавно изживяване, към което сме свикнали.
| **Навигация** | Пълно презареждане на страницата за всеки екран | Моментално превключване на съдържанието |
| **Производителност** | По-бавно заради пълно изтегляне на HTML | По-бързо с частични актуализации |
| **Потребителско изживяване** | Раздразнителни мигания на страницата | Гладки, като приложения, преходи |
| **Споделяне на данни** | Трудно между страниците | Лесно управление на състоянието |
| **Разработка** | Поддръжка на множество HTML файлове | Един HTML с динамични шаблони |
| **Разработка** | Множество HTML файлове за поддръжка | Един HTML с динамични шаблони |
**Разбиране на еволюцията:**
- **Традиционните приложения** изискват заявки към сървъра за всяко действие на навигация
- **Модерните SPAs** се зареждат веднъж и актуализират съдържанието динамично с помощта на JavaScript
- **Очакванията на потребителите** вече предпочитат моментални, безпроблемни взаимодействия
- **Предимства в производителността** включват намалена честотна лента и по-бързи отговори
- **Традиционните приложения** изискват заявка към сървъра за всяко навигационно действие
- **Модерните SPA** се зареждат веднъж и динамично обновяват съдържанието с JavaScript
- **Очакванията на потребителите** са за мигновени, безпроблемни взаимодействия
- **Предимствата в производителността** включват по-малка употреба на трафик и по-бързи отговори
В този урок ще създадем банково приложение смножество екрани, които плавно преминават един в друг. Както учените използват модулни инструменти, които могат да бъдат преконфигурирани за различни експерименти, ние ще използваме HTML шаблони като многократно използваеми компоненти, които могат да бъдат показвани при нужда.
В този урок ще създадем банково приложение сняколко екрана, които плавно се свързват. Подобно на начина, по който учените използват модулни инструменти, които могат да се пренастроят за различни експерименти, ще използваме HTML шаблони като многократно използваеми компоненти, които се показват при нужда.
Ще работите с HTML шаблони (многократно използваеми чертежи за различни екрани), JavaScript маршрутизация (система, която превключва между екраните) и API за историята на браузъра (който поддържа бутона за връщане назад да работи както се очаква). Това са същите основни техники, използвани от рамки като React, Vue и Angular.
Ще работите с HTML шаблони (многократно използваеми проектни планове за различни екрани), маршрутизация с JavaScript (системата, която превключва между екрани) и API за история на браузъра (който пази бутона назад да работи както се очаква). Това са същите основни техники, използвани от рамки като React, Vue и Angular.
До края ще имате работещо банково приложение, което демонстрира професионални принципи на едностраничните приложения.
На края ще имате работещо банково приложение, което демонстрира професионални принципи на едностранични приложения.
[Предварителен тест преди лекцията](https://ff-quizzes.netlify.app/web/quiz/41)
### Какво ще ви е необходимо
### Какво ще ви трябва
Ще ни трябва локален уеб сървър, за да тестваме нашето банково приложение – не се притеснявайте, това е по-лесно, отколкото звучи! Ако все още нямате такъв, просто инсталирайте [Node.js](https://nodejs.org) и изпълнете `npx lite-server` от папката на вашия проект. Тази удобна команда стартира локален сървър и автоматично отваря вашето приложение в браузъра.
Ще ни трябва локален уеб сървър за тестване на банковото ни приложение – не се притеснявайте, по-лесное, отколкото звучи! Ако нямате такъв, просто инсталирайте [Node.js](https://nodejs.org) и стартирайте `npx lite-server` в папката на проекта си. Тази полезна команда ще стартира локален сървър и автоматично ще отвори приложението ви в браузъра.
### Подготовка
На вашия компютър създайте папка с име `bank`с файл `index.html` вътре. Ще започнем с този HTML [шаблон](https://en.wikipedia.org/wiki/Boilerplate_code):
Накомпютъра си създайте папка на име `bank`, в която да има файл с името `index.html`. Ще започнем от този HTML [шаблон](https://en.wikipedia.org/wiki/Boilerplate_code):
```html
<!DOCTYPE html>
@ -62,15 +107,15 @@ CO_OP_TRANSLATOR_METADATA:
```
**Ето какво предоставя този шаблон:**
- **Установява** структурата на HTML5 документа с правилна декларация DOCTYPE
- **Конфигурира** кодировката на символите като UTF-8 за поддръжка на международен текст
- **Активира** адаптивен дизайн смета таг за изглед за мобилна съвместимост
- **Задава** описателно заглавие, което се появява в раздела на браузъра
- **Създава** чиста секция за тялото, където ще изградим нашето приложение
- **Установява** структурата на HTML5 документа с правилна декларация на DOCTYPE
- **Конфигурира** кодировката на символите като UTF-8 за международна поддръжка на текст
- **Активира** адаптивен дизайн сviewport мета таг за съвместимост с мобилни устройства
- **Задава** описателно заглавие, което се показва в таба на браузъра
- **Създава** чисто тяло, в което ще изграждаме приложението си
> 📁 **Преглед на структурата на проекта**
>
> **До края на този урок вашият проект ще съдържа:**
> **Към края на този урок проектът ви ще съдържа:**
> ```
> bank/
> ├── index.html <!-- Main HTML with templates -->
@ -79,42 +124,59 @@ CO_OP_TRANSLATOR_METADATA:
> ```
>
> **Отговорности на файловете:**
> - **index.html**: Съдържа всички шаблони и предоставя структурата на приложението
> - **index.html**: Съдържа всички шаблони и осигурява структурата на приложението
> - **app.js**: Управлява маршрутизацията, навигацията и управлението на шаблоните
> - **Шаблони**: Определят потребителския интерфейс за вход, табло и други екрани
> - **Шаблони**: Дефинират UI за вход, табло и други екрани
---
## HTML шаблони
## HTML Шаблони
Шаблоните решават основен проблем в уеб разработката. Когато Гутенберг изобретил печатането с подвижни букви през 1440-те години, той осъзнал, че вместо да издълбава цели страници, може да създаде многократно използваеми блокове с букви и да ги подрежда според нуждите. HTML шаблоните работят на същия принцип – вместо да създавате отделни HTML файлове за всеки екран, дефинирате многократно използваеми структури, които могат да бъдат показвани при нужда.
Шаблоните разрешават фундаментален проблем в уеб разработката. Когато Гутенберг изобретил подвижния печат през 1440-те, той осъзнал, че вместо да изрязва цели страници, може да създава многократно използваеми буквени блокчета и да ги подрежда според нуждите. HTML шаблоните работят по същия принцип – вместо да създават отделни HTML файлове за всеки екран, дефинирате многократно използваеми структури, които могат да се показват при нужда.
Помислете за шаблоните като за чертежи на различни части от вашето приложение. Точно както архитект създава един чертеж и го използва многократно, вместо да прерисува идентични стаи, ние създаваме шаблони веднъж и ги използваме при нужда. Браузърът държи тези шаблони скрити, докато JavaScript не ги активира.
```mermaid
flowchart TD
A["📋 Дефиниция на Шаблон"] --> B["💬 Скрит в DOM"]
B --> C["🔍 JavaScript Намира Шаблона"]
C --> D["📋 Копиране на Съдържанието на Шаблона"]
D --> E["🔗 Прикрепване към Видимия DOM"]
E --> F["👁️ Потребителят Вижда Съдържанието"]
G["Шаблон за Вход"] --> A
H["Шаблон за Табло"] --> A
I["Бъдещи Шаблони"] --> A
style A fill:#e3f2fd
style D fill:#e8f5e8
style F fill:#fff3e0
style B fill:#f3e5f5
```
Мислете за шаблоните като за планове за различни части от вашето приложение. Както архитектът създава един план и го използва многократно, вместо да чертае еднакви стаи наново, така и ние създаваме шаблон веднъж и го използваме при нужда. Браузърът държи тези шаблони скрити, докато JavaScript не ги активира.
Ако искате да създадете множество екрани за уеб страница, едно решение би било да създадете един HTML файл за всеки екран, който искате да покажете. Въпреки това, това решение идва с някои неудобства:
Ако искате да създадете няколко екрана за уеб страница, едно решение е да направите по един HTML файл за всеки екран. Този подход обаче има неудобства:
- Трябва да презареждате целия HTML при смяна на екрана, което може да бъде бавно.
- Трудно е да споделяте данни между различните екрани.
- Трудно е да сесподелят данни между различните екрани.
Друг подход е да имате само един HTML файл и да дефинирате множество [HTML шаблони](https://developer.mozilla.org/docs/Web/HTML/Element/template), използвайки елемента `<template>`. Шаблонът е многократно използваем HTML блок, който не се показва от браузъра и трябва да бъде създаден по време на изпълнение с помощта на JavaScript.
Друго решение е да имате само един HTML файл и да дефинирате няколко [HTML шаблона](https://developer.mozilla.org/docs/Web/HTML/Element/template) чрез елемента `<template>`. Шаблонът е многократно използваем HTML блок, който браузърът не показва и който трябва да бъде „инстанциран“ по време на изпълнение с помощта на JavaScript.
### Да го изградим
### Нека го създадем
Ще създадем банково приложение с два основни екрана: страница за вход и табло. Първо, нека добавим елемент за запълване към тялото на нашия HTML – това е мястото, където ще се появят всички наши различни екрани:
Ще направим банково приложение с два основни екрана: страница за вход и табло. Първо, нека добавим запълващ елемент в тялото на HTML – тук ще се появяват всички различни екрани:
```html
<divid="app">Loading...</div>
```
**Разбиране на този елемент за запълване:**
- **Създава** контейнер с ID "app", където ще се показват всички екрани
**Какво прави този плейсхолдър:**
- **Създава** контейнер с ID „app“, където ще се показват всички екрани
- **Показва** съобщение за зареждане, докато JavaScript инициализира първия екран
- **Осигурява** един точка за монтиране на нашето динамично съдържание
- **Позволява** лесно насочване от JavaScript, използвайки`document.getElementById()`
- **Осигурява** една точка на закрепване за динамичното съдържание
- **Позволява** лесно насочване от JavaScript чрез`document.getElementById()`
> 💡 **Полезен съвет**: Тъй като съдържанието на този елемент ще бъде заменено, можем да поставим съобщение за зареждане или индикатор, който ще се показва, докато приложението се зарежда.
> 💡 **Профи съвет**: Тъй като съдържанието на този елемент ще се заменя, можем да сложим съобщение или индикатор за зареждане, което ще се показва докато приложението се зарежда.
След това нека добавим HTML шаблон за страницата за вход. Засега ще поставим само заглавие и секция, съдържаща връзка, която ще използваме за навигация.
След това нека добавим под него HTML шаблона за страницата за вход. За момента ще сложим само заглавие и секция със връзка, която ще ползваме за навигацията.
```html
<templateid="login">
@ -125,15 +187,15 @@ CO_OP_TRANSLATOR_METADATA:
</template>
```
**Разбивка на този шаблон за вход:**
- **Дефинира** шаблон с уникален идентификатор "login" за насочване от JavaScript
- **Включва** основно заглавие, което установява брандирането на приложението
**Какво съдържа този шаблон за вход:**
- **Дефинира** шаблон с уникален идентификатор „login“ за насочване с JavaScript
- **Включва** основно заглавие, което задава бранда на приложението
- **Съдържа** семантичен елемент `<section>` за групиране на свързано съдържание
- **Осигурява** навигационна връзка, която ще насочва потребителите към таблото
- **Осигурява** навигационна връзка, която ще пренасочва потребителите към таблото
След това ще добавим друг HTML шаблон за страницата на таблото. Тази страница ще съдържа различни секции:
След това добавяме друг HTML шаблон за страницата с табло. Тази страница ще има различни секции:
- Заглавие със заглавие и връзка за изход
- Заглавен блок с титул и връзка за изход
- Текущото салдо на банковата сметка
- Списък с транзакции, показан в таблица
@ -162,73 +224,88 @@ CO_OP_TRANSLATOR_METADATA:
</template>
```
**Нека разберем всяка част от това табло:**
- **Структурира** страницата със семантичен елемент `<header>`, съдържащ навигация
- **Показва** заглавието на приложението последователно на всички екрани за брандиране
- **Осигурява** връзка за изход, която насочва обратно към екрана за вход
- **Показва** текущото салдо на сметката в специална секция
- **Организира** данните за транзакциите,използвайки правилно структурирана HTML таблица
- **Дефинира** заглавия на таблицата за колони Дата, Обект и Сума
**Нека разберем всеки елемент на таблото:**
- **Структурира** страницата със семантичен елемент `<header>`, който съдържа навигация
- **Показва** заглавието на приложението за консистентност в различните екрани
- **Осигурява** връзка за изход, която пренасочва обратно към екрана за вход
- **Показва** текущото салдо в отделена секция
- **Организира** данните за транзакциите в правилно структурирана HTML таблица
- **Дефинира** заглавия на колоните Дата, Обект и Сума
- **Оставя** тялото на таблицата празно за динамично добавяне на съдържание по-късно
> 💡 **Полезен съвет**: Когато създавате HTML шаблони, ако искате да видите как ще изглеждат, можете да коментирате линиите `<template>` и `</template>`, като ги оградите с`<!-- -->`.
> 💡 **Профи съвет**: Когато създавате HTML шаблони, ако искате да видите как ще изглежда, можете да коментирате редовете `<template>` и `</template>`, като ги обградите с`<!-- -->`.
### 🔄 **Педагогическа проверка**
**Разбиране на системата с шаблони**: Преди да имплементирате JavaScript, уверете се, че разбирате:
- ✅ Какво различава шаблоните от обикновените HTML елементи
- ✅ Защо шаблоните остават скрити, докато не бъдат активирани от JavaScript
- ✅ Значението на семантичната HTML структура в шаблоните
- ✅ Как шаблоните позволяват многократна употреба на UI компоненти
**Бърз само тест**: Какво се случва, ако премахнете таговете `<template>` от вашия HTML?
*Отговор: Съдържанието става видимо веднага и губи функционалността на шаблон*
**Предимства на архитектурата**: Шаблоните осигуряват:
- **Многократна употреба**: Една дефиниция – множество инстанции
- **Производителност**: Без излишно парсване на HTML
- **Поддръжка**: Централизирана структура на UI
- **Гъвкавост**: Динамична смяна на съдържанието
✅ Защо мислите, че използваме атрибути `id` върху шаблоните? Можем ли да използваме нещо друго, като класове?
✅ Защо според вас използваме `id` атрибути на шаблоните? Можем ли да използваме нещо друго, като класове?
## Оживяване на шаблоните с JavaScript
Сега трябва да направим нашите шаблони функционални. Точно както 3D принтер превръща цифров чертеж във физически обект, JavaScript взема нашите скрити шаблони и създава видими, интерактивни елементи, които потребителите могат да видят и използват.
Сега трябва да направим шаблоните функционални. Както 3D принтерът приема цифров план и създава физически обект, така и JavaScript взема нашите скрити шаблони и създава видими, интерактивни елементи, които потребителите могат да виждат и използват.
Процесът следва три последователни стъпки, които формират основата на съвременната уеб разработка. След като разберете този модел, ще го разпознаете в много рамки и библиотеки.
Процесът следва три последователни стъпки, които са основата на модерната уеб разработка. Когато разберете този модел, ще го разпознавате в много рамки и библиотеки.
Ако опитате текущия HTML файл в браузър, ще видите, че той остава на `Loading...`. Това е така, защото трябва да добавим малко JavaScript код, за да създадем и покажем HTML шаблоните.
Ако отворите текущия си HTML файл в браузъра, ще видите, че остава на екрана `Loading...`. Това е защото трябва да добавим JavaScript код, който да инстанцира и покаже HTML шаблоните.
Създаването на шаблон обикновено се извършва в 3 стъпки:
Инстанцирането на шаблон обикновено става в 3 стъпки:
1. Извличане на елемента шаблон в DOM, например с [`document.getElementById`](https://developer.mozilla.org/docs/Web/API/Document/getElementById).
2. Клониране на елемента шаблон, използвайки [`cloneNode`](https://developer.mozilla.org/docs/Web/API/Node/cloneNode).
3. Прикачване към DOM под видим елемент, например с [`appendChild`](https://developer.mozilla.org/docs/Web/API/Node/appendChild).
1. Извличане на елемента шаблон в DOM, например чрез [`document.getElementById`](https://developer.mozilla.org/docs/Web/API/Document/getElementById).
2. Клониране на шаблонния елемент, използвайки [`cloneNode`](https://developer.mozilla.org/docs/Web/API/Node/cloneNode).
3. Прикрепяне към DOM под видим елемент, например чрез [`appendChild`](https://developer.mozilla.org/docs/Web/API/Node/appendChild).
- **Стъпка 1** намира скрития шаблон в структурата на DOM
- **Стъпка 2** създава работно копие, което може безопасно да се модифицира
- **Стъпка 3** вмъква копието в видимата област на страницата
**Визуално разграждане на процеса:**
- **Стъпка 1** намира скрития шаблон в DOM структурата
- **Стъпка 2** създава работно копие, което може да бъде безопасно променяно
- **Стъпка 3** вмъква копието във видимата област на страницата
- **Резултат** е функционален екран, с който потребителите могат да взаимодействат
✅ Защо трябва да клонираме шаблона, преди да го прикачим към DOM? Какво мислите, че би се случило, ако пропуснем тази стъпка?
✅ Защо трябва да клонираме шаблона преди да го прикачим към DOM? Какво смятате, че ще стане, ако пропуснем тази стъпка?
### Задача
Създайте нов файл с име `app.js` в папката на вашия проект и го импортирайте в секцията `<head>` на вашия HTML:
Създайте нов файл на име `app.js` в папката на проекта и импортирайте този файл в секцията `<head>` на вашия HTML:
```html
<scriptsrc="app.js"defer></script>
```
**Разбиране на този скрипт за импортиране:**
**Разбиране на този импорт на скрипт:**
- **Свързва** JavaScript файла с нашия HTML документ
- **Използва** атрибута `defer`, за да гарантира, че скриптът се изпълнява след завършване на анализа на HTML
- **Осигурява** достъп до всички DOM елементи, тъй като теса напълно заредени преди изпълнението на скрипта
- **Следва** съвременни най-добри практики за зареждане на скриптове и производителност
- **Използва** атрибута `defer` за да се увери, че скриптът се изпълнява след като HTML парсването приключи
- **Позволява** достъп до всички DOM елементи, понежеса напълно заредени преди изпълнението на скрипта
- **Следва** съвременни добри практики за зареждане на скриптове и производителност
Сега в `app.js` ще създадем нова функция `updateRoute`:
Сега, в `app.js`, ще създадем нова функция `updateRoute`:
```js
function updateRoute(templateId) {
@ -239,57 +316,72 @@ function updateRoute(templateId) {
app.appendChild(view);
}
```
**Стъпка по стъпка, ето какво се случва:**
- **Намира** елемента шаблон, използвайки неговия уникален ID
- **Създава** дълбоко копие на съдържанието на шаблона, използвайки`cloneNode(true)`
- **Намира** контейнера на приложението, където съдържанието ще бъде показано
- **Изчиства** всяко съществуващо съдържание от контейнера на приложението
- **Намира** елемента шаблон чрез уникалния му ID
- **Създава** дълбоко копие на съдържанието на шаблона чрез`cloneNode(true)`
- **Намира** контейнера на приложението, където ще се показва съдържанието
- **Изчиства** всяко съществуващо съдържание от контейнера
- **Вмъква** клонираното съдържание на шаблона във видимия DOM
Сега извикайте тази функция с един от шаблоните и вижте резултата.
Сега извикайте тази функция с един от шаблоните и разгледайте резултата.
```js
updateRoute('login');
```
**Какво постига това извикване на функцията:**
- **Активира** шаблона за вход, като предава неговия ID като параметър
**Какво прави това извикване на функция:**
- **Активира** шаблона за вход, като предава неговото ID като параметър
- **Демонстрира** как програмно да се превключва между различни екрани на приложението
- **Показва** екрана за вход вместо съобщението "Loading..."
- **Показва** екрана за вход вместо съобщението „Loading...“
✅ Каква е целта на този код `app.innerHTML = '';`? Какво се случва без него?
## Създаване на маршрути
Маршрутизацията по същество е свързана с свързването на URL адреси с правилното съдържание. Помислете как ранните телефонни оператори използваха комутатори, за да свързват обаждания – те приемаха входяща заявка и я насочваха към правилната дестинация. Уеб маршрутизацията работи по подобен начин, като приема заявка за URL и определя кое съдържание да се покаже.
Традиционно уеб сървърите се справяха с това, като предоставяха различни HTML файлове за различни URL адреси. Тъй като изграждаме едностранично приложение, трябва сами да се справим с тази маршрутизация с помощта на JavaScript. Този подход ни дава повече контрол върху потребителското изживяване и производителността.
Маршрутизацията по същество свързва URL адреси с правилното съдържание. Помислете за това как ранните телефонни оператори използвали комутационни табла за свързване на повиквания – те приемали входящата заявка и я пренасочвали към правилната дестинация. Уеб маршрутизацията работи по подобен начин, като приема URL заявка и решава кое съдържание да покаже.
D --> E["👁️ Показване на Екран<br/>Клониране & Добавяне"]
F["📍 /login"] --> G["🎯 'login'"]
H["📍 /unknown"] --> I["❌ Not Found"]
I --> J["🔄 Redirect to /login"]
H["📍 /unknown"] --> I["❌ Нее намерено"]
I --> J["🔄 Пренасочване към /login"]
style B fill:#e3f2fd
style E fill:#e8f5e8
style I fill:#ffebee
style J fill:#fff3e0
```
Традиционно, уеб сървърите обработват това, като обслужват различни HTML файлове за различни URL адреси. Тъй като изграждаме едностранично приложение, трябва да се справим с това сами чрез JavaScript. Този подход ни дава по-голям контрол върху потребителското изживяване и производителността.
**Разбиране на потока на маршрутизацията:**
- **Промените в URL** предизвикват търсене в конфигурацията на маршрутите
- **Валидните маршрути** се свързват със специфични ID на шаблони за рендиране
- **Невалидните маршрути** предизвикват резервно поведение, за да се предотвратят грешки
- **Рендирането на шаблони** следва трите стъпки, които научихме по-рано
C --> D["📄 Намиране на Шаблон<br/>getElementById"]
D --> E["👁️ Показване на Екран<br/>Клониране & Добавяне"]
F["📍 /login"] --> G["🎯 'login'"]
H["📍 /unknown"] --> I["❌ Нее намерено"]
I --> J["🔄 Пренасочване към /login"]
style B fill:#e3f2fd
style E fill:#e8f5e8
style I fill:#ffebee
style J fill:#fff3e0
```
**Разбиране на потока на маршрутизация:**
- **Промяна на URL** задейства проверка в конфигурацията ни за маршрути
- **Валидните маршрути** се свързват с конкретни ID-та на шаблони за рендиране
- **Невалидните маршрути** задействат резервно поведение, за да предотвратят повредени състояния
- **Рендирането на шаблон** следва трите стъпки, които научихме по-рано
Когато говорим за уеб приложение, наричаме *Маршрутизация* намерението да се свържат **URL адреси** със специфични екрани, които трябва да бъдат показани. На уебсайт с множество HTML файлове това се прави автоматично, тъй като пътеките на файловете се отразяват в URL адреса. Например, с тези файлове във вашата проектна папка:
Когато говорим за уеб приложение, наричаме *маршрутизация* намерението да свържем **URL адреси**с конкретни екрани, които трябва да се покажат. В уебсайт с множество HTML файлове това се случва автоматично, тъй като пътеките на файловете се отразяват в URL адреса. Например с тези файлове във вашата проектна папка:
```
mywebsite/index.html
@ -297,7 +389,7 @@ mywebsite/login.html
mywebsite/admin/index.html
```
Ако създадете уеб сървър с`mywebsite` като корен, картографирането на URL адресите ще бъде:
Ако създадете уеб сървър с`mywebsite` като корен, картографирането на URL адреси ще бъде:
Въпреки това, за нашето уеб приложение използваме един HTML файл, съдържащ всички екрани, така че това стандартно поведение няма да ни помогне. Трябва да създадем тази карта ръчно и да актуализираме показания шаблон с помощ
✅ Какво се случва, ако въведете неизвестен път в URL? Как можем да решим това?
Обаче за нашето уеб приложение използваме един HTML файл, съдържащ всички екрани, така че това поведение по подразбиране няма да е от полза. Трябва да създадем тази карта ръчно и да обновяваме показвания шаблон с JavaScript.
### Задача
Ще използваме прост обект за реализиране на [карта](https://en.wikipedia.org/wiki/Associative_array) между URL пътища и нашите шаблони. Добавете този обект в началото на файла `app.js`.
```js
const routes = {
'/login': { templateId: 'login' },
'/dashboard': { templateId: 'dashboard' },
};
```
**Разбиране на тази конфигурация за маршрути:**
- **Дефинира** картографиране между URL пътища и идентификатори на шаблони
- **Използва** синтаксис на обект, където ключовете са URL пътища, а стойностите съдържат информация за шаблона
- **Позволява** лесно търсене кой шаблон да бъде показан за даден URL
- **Осигурява** мащабируема структура за добавяне на нови маршрути в бъдеще
Сега нека модифицираме малко фунцкията `updateRoute`. Вместо да подаваме директно `templateId` като аргумент, искаме първо да го извлечем, като разгледаме текущия URL, а след това използваме нашата карта, за да получим съответстващата стойност на шаблонния ID. Можем да използваме [`window.location.pathname`](https://developer.mozilla.org/docs/Web/API/Location/pathname), за да вземем само пътя от URL.
- **Извлича** текущия път от URL на браузъра, използвайки `window.location.pathname`
- **Търси** съответстващата конфигурация за маршрут в нашия обект routes
- **Извлича** ID на шаблона от конфигурацията на маршрута
- **Следва** същия процес за рендиране на шаблона както преди
- **Създава** динамична система, която реагира на промени в URL
Тук свързахме маршрутите, които обявихме, с съответния шаблон. Можете да тествате дали работи правилно, като ръчно промените URL в браузъра си.
✅ Какво се случва, ако въведете непознат път в URL? Как бихме могли да решим това?
## Добавяне на навигация
С установеното маршрутизиране, потребителите се нуждаят от начин да се придвижват из приложението. Традиционните уебсайтове презареждат цели страници при кликване върху връзки, но ние искаме да актуализираме както URL адреса, така и съдържанието без презареждане на страницата. Това създава по-гладко изживяване, подобно на това как настолните приложения превключват между различни изгледи.
С установено маршрутизиране, потребителите се нуждаят от начин да навигират в приложението. Традиционните сайтове презареждат цели страници при клик върху връзки, но искаме да обновим както URL, така и съдържанието без презареждане на страницата. Това създава по-гладко преживяване, подобно на това как настолните приложения превключват между различни изгледи.
Трябва да координираме две неща: актуализиране на URL адреса на браузъра, за да могат потребителите да запазват страници и да споделят връзки, и показване на подходящото съдържание. Когато това е правилно реализирано, се създава безпроблемна навигация, която потребителите очакват от съвременните приложения.
Трябва да координираме две неща: да обновим URL на браузъра, за да могат потребителите да маркират и споделят страници, и да покажем съответното съдържание. При правилна реализация това създава безпроблемна навигация, каквато потребителите очакват от модерните приложения.
> 🏗️ **Информация за архитектурата**: Компоненти на навигационната система
Следващата стъпка за нашето приложение е да добавим възможност за навигация между страниците, без да се налага ръчно да променяме URL адреса. Това предполага две неща:
Следващата стъпка за нашето приложение е да добавим възможност за навигация между страници без ръчна смяна на URL. Това означава две неща:
1. Актуализиране на текущия URL адрес
2. Актуализиране на показания шаблон според новия URL адрес
1. Обновяване на текущия URL
2. Обновяване на показвания шаблон според новия URL
Вече се погрижихме за втората част с функцията `updateRoute`, така че трябва да разберем как да актуализираме текущия URL адрес.
Вече се погрижихме за втората част с функцията `updateRoute`, затова трябва да измислим как да обновим текущия URL.
Ще трябва да използваме JavaScript и по-конкретно [`history.pushState`](https://developer.mozilla.org/docs/Web/API/History/pushState), който позволява актуализиране на URL адреса и създаване на нов запис в историята на браузъра, без да се презарежда HTML.
Ще трябва да използваме JavaScript, а по-конкретно [`history.pushState`](https://developer.mozilla.org/docs/Web/API/History/pushState), която позволява да обновим URL и да създадем нов запис в историята на браузъра, без да презареждаме HTML.
> ⚠️ **Важно уточнение**: Въпреки че HTML елементът за връзка [`<a href>`](https://developer.mozilla.org/docs/Web/HTML/Element/a) може да се използва самостоятелно за създаване на хипервръзки към различни URL адреси, той по подразбиране ще накара браузъра да презареди HTML. Необходимо е да се предотврати това поведение при обработка на маршрутизация с персонализиран JavaScript, като се използва функцията preventDefault() върху събитието за кликване.
> ⚠️ **Важно:** Докато HTML елементът [`<a href>`](https://developer.mozilla.org/docs/Web/HTML/Element/a) може да се използва самостоятелно за създаване на хипервръзки към различни URL, той по подразбиране кара браузъра да презареди HTML. Необходимо е да се предотврати това поведение при работа с маршрутизиране чрез собствен JavaScript, като се използва функцията preventDefault() на събитието click.
### Задача
Нека създадем нова функция, която можем да използваме за навигация в нашето приложение:
Нека създадем нова функция, която можем да използваме за навигация в приложението ни:
```js
function navigate(path) {
@ -351,14 +533,14 @@ function navigate(path) {
```
**Разбиране на тази навигационна функция:**
- **Актуализира** URL адреса на браузъра към новия път с`history.pushState`
- **Добавя** нов запис в стека на историята на браузъра за правилна поддръжка на бутоните за назад/напред
- **Обновява** URL в браузъра с новия път, използвайки`history.pushState`
- **Добавя** нов запис в историята на браузъра за поддръжка на бутоните назад/напред
- **Задейства** функцията `updateRoute()`, за да покаже съответния шаблон
- **Поддържа** изживяването на едностраничното приложение без презареждане на страницата
- **Поддържа** преживяването на едностранично приложение без презареждане на страницата
Този метод първо актуализира текущия URL адрес според дадения път, след което актуализира шаблона. Свойството `window.location.origin` връща корена на URL адреса, което ни позволява да реконструираме пълен URL адрес от даден път.
Този метод първо обновява текущия URL на база зададения път, след това обновява шаблона. Свойството `window.location.origin` връща корена на URL, позволявайки ни да реконструираме пълен URL от даден път.
Сега, когато имаме тази функция, можем да се погрижим за проблема, който имаме, ако пътят не съответства на някой от дефинираните маршрути. Ще модифицираме функцията `updateRoute`, като добавим резервен вариант към един от съществуващите маршрути, ако не можем да намерим съвпадение.
Сега, след като имаме тази функция, можем да разрешим проблема, ако път не съвпада с нито един дефиниран маршрут. Ще модифицираме `updateRoute`, като добавим резервен маршрут към съществуващ такъв, ако не можем да намерим съвпадение.
```js
function updateRoute() {
@ -377,15 +559,15 @@ function updateRoute() {
}
```
**Основни точки за запомняне:**
**Ключови моменти за запомняне:**
- **Проверява** дали съществува маршрут за текущия път
- **Пренасочва** към страницата за вход, когато се достъпи невалиден маршрут
- **Пренасочва** към страницата за вход при достъп до невалиден маршрут
- **Осигурява** резервен механизъм, който предотвратява счупена навигация
- **Гарантира**, че потребителите винаги виждат валиден екран, дори при неправилни URL адреси
- **Гарантира**, че потребителите винаги виждат валиден екран, дори при грешни URL
Ако не може да се намери маршрут, сега ще пренасочваме към страницата `login`.
Ако маршрута не съществува, сега ще пренасочим към страницата `login`.
Сега нека създадем функция, която да получава URL адреса, когато се кликне върху връзка, и да предотвратява стандартното поведение на браузъра при кликване върху връзка:
Сега нека създадем функция, която получава URL при клик върху линк и предотвратява стандартното поведение на браузъра:
```js
function onLinkClick(event) {
@ -394,11 +576,11 @@ function onLinkClick(event) {
}
```
**Разбивка на този обработчик на кликвания:**
- **Предотвратява** стандартното поведение на браузъра при кликване върху връзкас`preventDefault()`
- **Извлича** целевия URL адрес от елемента на кликнатата връзка
- **Извиква** нашата персонализирана функция за навигация вместо презареждане на страницата
- **Поддържа** гладкото изживяване на едностраничното приложение
**Разбиване на този обработчик при клик:**
- **Предотвратява** стандартното поведение на линковетес`preventDefault()`
- **Извлича** URL на дестинацията от елемента, върху който е кликнато
- **Извиква** нашата потребителска функция за навигация, вместо да презарежда страницата
- **Поддържа** гладкото потребителско изживяване на едностранично приложение
@ -407,22 +589,22 @@ function onLinkClick(event) {
```
**Какво постига това свързване на onclick:**
- **Свързва** всяка връзка с нашата персонализирана навигационна система
- **Предава** събитието за кликване на нашата функция `onLinkClick` за обработка
- **Свързва** всеки линк с нашата система за навигация
- **Предава** събитието click към нашата функция `onLinkClick` за обработка
- **Позволява** гладка навигация без презареждане на страницата
- **Поддържа** правилната структура на URL адреса, която потребителите могат да запазват или споделят
- **Поддържа** правилна URL структура, която потребителите могат да маркират или споделят
Атрибутът [`onclick`](https://developer.mozilla.org/docs/Web/API/GlobalEventHandlers/onclick) свързва събитието за кликванес JavaScript код, тук извикването на функцията `navigate()`.
Атрибутът [`onclick`](https://developer.mozilla.org/docs/Web/API/GlobalEventHandlers/onclick) свързва събитието `click`с JavaScript код, тук извикването на функцията `navigate()`.
Опитайте да кликнете върху тези връзки, вече трябва да можете да навигирате между различните екрани на вашето приложение.
Опитайте да кликнете на тези линкове, сега трябва да можете да навигирате между различните екрани на приложението.
✅ Методът `history.pushState`е част от стандарта HTML5 и е имплементиран във [всички съвременни браузъри](https://caniuse.com/?search=pushState). Ако изграждате уеб приложение за по-стари браузъри, има трик, който можете да използвате вместо този API: използвайки [хаш (`#`)](https://en.wikipedia.org/wiki/URI_fragment) преди пътя, можете да реализирате маршрутизация, която работи с обикновена навигация чрез анкери и не презарежда страницата, тъй като целта му е да създава вътрешни връзки в рамките на една страница.
✅ Методът `history.pushState`е част от стандарта HTML5 и е имплементиран в [всички модерни браузъри](https://caniuse.com/?search=pushState). Ако разработвате уеб приложение за по-стари браузъри, има трик, който може да използвате като заместител на този API: използване на [hash (`#`)](https://en.wikipedia.org/wiki/URI_fragment) преди пътя, с което можете да имплементирате маршрутизиране, което работи с обикновени хипервръзки и не презарежда страницата, тъй като е било предназначено за създаване на вътрешни препратки в страницата.
## Осигуряване на работа на бутоните за назад и напред
## Правене на бутоните за назад и напред в браузъра да работят
Бутоните за назад и напред са основни за уеб браузването, подобно на това как контролерите на мисии на НАСА могат да преглеждат предишни състояния на системата по време на космически мисии. Потребителите очакват тези бутони да работят, и когато не го правят, това нарушава очакваното изживяване при браузване.
Бутоните назад и напред са фундаментални за уеб разглеждането, подобно на това как контролерите на мисии на НАСА могат да преглеждат предишни състояния на системата по време на космически мисии. Потребителите очакват тези бутони да работят, и когато не работят, нарушава нормалното изживяване при браузване.
Нашето едностранично приложение се нуждае от допълнителна конфигурация, за да поддържа това. Браузърът поддържа стек на историята (който добавяме с`history.pushState`), но когато потребителите навигират през тази история, нашето приложение трябва да реагира, като съответно актуализира показаното съдържание.
Нашето едностранично приложение се нуждае от допълнителна конфигурация, за да ги поддържа. Браузърът поддържа стек с история (в който вече добавяме записи с`history.pushState`), но когато потребителите навигират в тази история, нашето приложение трябва да реагира, като обнови показваното съдържание съответно.
Browser->>Browser: URL се актуализира на /dashboard
App->>App: updateRoute() извикано
App->>Template: Намери и клонирай шаблон за табло
Template->>App: Върни клонирано съдържание
App->>Browser: Замени съдържанието на приложението с шаблона
Browser->>User: Показване на екран на табло
Note over User,Template: User clicks browser back button
Note over User,Template: Потребителят кликва върху бутона за връщане на браузъра
User->>Browser: Clicks back button
Browser->>Browser: History moves back to /login
Browser->>App: popstate event fired
App->>App: updateRoute() called automatically
App->>Template: Find & clone login template
Template->>App: Return cloned content
App->>Browser: Replace app content with template
Browser->>User: Display login screen
User->>Browser: Кликва върху бутона за връщане
Browser->>Browser: Историята се връща към /login
Browser->>App: popstate събитие задействано
App->>App: updateRoute() извикано автоматично
App->>Template: Намери и клонирай шаблон за вход
Template->>App: Върни клонирано съдържание
App->>Browser: Замени съдържанието на приложението с шаблона
Browser->>User: Показване на екран за вход
```
**Ключови точки на взаимодействие:**
- **Потребителски действия** тригерират навигация чрез кликове или бутоните на браузъра
- **Приложението прихваща** кликвания на линкове, за да предотврати презареждане на страницата
- **History API** управлява промяна на URL и стека на историята
- **Шаблоните** осигуряват структурата на съдържанието за всеки екран
- **Слушатели на събития** гарантират, че приложението реагира на всички типове навигация
**Основни точки на взаимодействие:**
- **Действията на потребителя** задействат навигация чрез кликове или бутони на браузъра
- **Приложението прихваща** кликове върху връзки, за да предотврати презареждане на страницата
- **History API** управлява промените в URL адресите и стека на историята на браузъра
- **Шаблоните** предоставят структурата на съдържанието за всеки екран
- **Слушателите на събития** гарантират, че приложението реагира на всички видове навигация
Използването на `history.pushState` създава нови записи в историята на браузъра. Можете да проверите това, като задържите *бутона за назад* на браузъра, той трябва да покаже нещо такова:
Използването на `history.pushState` създава нови записи в историята на навигацията на браузъра. Можете да проверите това, като задържите *бутона за назад* на вашия браузър, трябва да се появи нещо подобно:


Ако опитате да кликнете няколко пъти върху бутона назад, ще видите, че текущият URL се променя и историята се обновява, но се показва все същият шаблон.
Ако опитате да кликнете върху бутона за назад няколко пъти, ще видите, че текущият URL адрес се променя и историята се актуализира, но същият шаблон продължава да се показва.
Това е така, защото приложението не знае, че трябва да извика `updateRoute()` всеки път, когато историята се промени. Ако погледнете документацията за [`history.pushState`](https://developer.mozilla.org/docs/Web/API/History/pushState), можете да видите, че ако състоянието се промени - което означава, че сме преминали към различен URL адрес - събитието [`popstate`](https://developer.mozilla.org/docs/Web/API/Window/popstate_event) се задейства. Ще използваме това, за да решим проблема.
Това е защото приложението не знае, че трябва да извика `updateRoute()` всеки път, когато историята се промени. Ако погледнете [документацията за `history.pushState`](https://developer.mozilla.org/docs/Web/API/History/pushState), ще видите, че при промяна на състоянието – т.е. когато преминаваме към различен URL –се задейства събитие [`popstate`](https://developer.mozilla.org/docs/Web/API/Window/popstate_event). Ще използваме това, за да оправим проблема.
### Задача
За да се уверим, че показаният шаблон се актуализира, когато историята на браузъра се промени, ще прикачим нова функция, която извиква `updateRoute()`. Ще направим това в края на файла`app.js`:
За да се уверим, че показваният шаблон се обновява при промени в историята на браузъра, ще прикрепим нова функция, която извиква `updateRoute()`. Ще гонаправим в края на нашия файл `app.js`:
```js
window.onpopstate = () => updateRoute();
@ -479,63 +660,174 @@ updateRoute();
```
**Разбиране на тази интеграция с историята:**
- **Слуша** събития `popstate`, които се случват, когато потребителите навигиратс бутоните на браузъра
- **Използва** стрелкова функция за кратък синтаксис на обработчика на събития
- **Автоматично извиква** `updateRoute()` всеки път, когато състоянието на историята се промени
- **Инициализира** приложението, като извиква `updateRoute()` при първото зареждане на страницата
- **Гарантира**, че правилният шаблон се показва независимо от начина, по който потребителите навигират
- **Слуша** за събития `popstate`, които се случват при навигацияс бутоните на браузъра
- **Използва** стрелкова функция за по-кратък синтаксис при обработката
- **Извиква** автоматично `updateRoute()`, когато състоянието на историята се промени
- **Инициализира** приложението, като извиква `updateRoute()` при първоначално зареждане
- **Гарантира** правилното показване на шаблона независимо от начина на навигация на потребителите
> 💡 **Съвет**: Използвахме [стрелкова функция](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Arrow_functions), за да декларираме обработчика на събития `popstate` за краткост, но обикновена функция би работила по същия начин.
> 💡 **Съвет:** Използвахме [стрелкова функция](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Arrow_functions) тук за обработчика на `popstate` за краткост, но и обикновена функция би работила по същия начин.
Ето видео за освежаване на знанията за стрелкови функции:
> 🎥 Кликнете върху изображението по-горе за видео за стрелкови функции.
> 🎥 Кликнете на картинката за видео за стрелкови функции.
Сега опитайте да използвате бутоните назад и напред в браузъра си и проверете дали показваният маршрут се обновява правилно този път.
### ⚡ **Какво можете да направите в следващите 5 минути**
- [ ] Тествайте навигацията на вашето банково приложение с бутоните назад/напред
- [ ] Опитайте ръчно да въвеждате различни URL адреси в адресната лента за тестване на маршрути
- [ ] Отворете DevTools на браузъра и инспектирайте как шаблоните се клонират в DOM
- [ ] Експериментирайте с добавяне на console.log съобщения за проследяване на потока на маршрутизиране
### 🎯 **Какво можете да постигнете този час**
- [ ] Попълнете теста след урока и разберете концепциите на архитектурата на SPA
- [ ] Добавете CSS стилизиране, за да изглеждат вашите банкови шаблони професионално
- [ ] Реализирайте страницата за грешка 404 с правилна обработка на грешки
- [ ] Създайте предизвикателство за страница с "credits" с допълнителна маршрутизация
- [ ] Добавете състояния за зареждане и преходи между смени на шаблони
### 📅 **Вашето седмично пътешествие в разработката на SPA**
- [ ] Завършете цялото банково приложение с формуляри, управление на данни и съхранение
- [ ] Добавете разширени функции за маршрутизиране като параметри на маршрути и вложени маршрути
- [ ] Имплементирайте навигационни предпазители и маршрутизиране с автентикация
- [ ] Създайте повторно използваеми шаблонни компоненти и библиотека с компоненти
- [ ] Добавете анимации и преходи за по-гладко потребителско изживяване
- [ ] Разположете вашето SPA на хостинг платформа и конфигурирайте маршрутирането правилно
### 🌟 **Ваше месечно овладяване на Frontend архитектурата**
- [ ] Създавайте сложни SPA с модерни рамки като React, Vue или Angular
- [ ] Учете разширени модели и библиотеки за управление на състоянието
- [ ] Оптимизирайте билд инструменти и работни потоци за разработка на SPA
- [ ] Имплементирайте функции за прогресивни уеб приложения и офлайн работа
- [ ] Изучавайте техники за оптимизация на производителността за мащабни SPA
- [ ] Допринасяйте към SPA проекти с отворен код и споделяйте знанията си
## 🎯 Вашият график за овладяване на едностранични приложения
Сега опитайте да използвате бутоните за назад и напред на вашия браузър и проверете дали показаният маршрут е правилно актуализиран този път.
```mermaid
timeline
title Развитие на SPA и Учебен прогрес по съвременна уеб архитектура
section Основи (20 минути)
Системи с шаблони: HTML елементи на шаблон
: Манипулация на DOM
: Клониране на съдържание
: Динамично визуализиране
section Основи на маршрутизацията (30 минути)
Клиентска навигация: Управление на URL адреси
: History API
: Картиране на маршрути
: Обработка на събития
section Потребителски опит (40 минути)
Полиране на навигацията: Интеграция с браузъра
: Поддръжка на бутон за връщане назад
: Обработка на грешки
: Плавни преходи
section Архитектурни модели (50 минути)
Професионални SPA: Системи за компоненти
: Управление на състоянието
: Оптимизация на производителността
: Граници за грешки
section Разширени техники (1 седмица)
Интеграция на фреймуърк: React Router
: Vue Router
: Angular Router
: Библиотеки за състояние
section Производствени умения (1 месец)
Корпоративна разработка: Системи за сборка
: Стратегии за тестване
: Канали за внедряване
: Мониторинг на производителността
```
### 🛠️ Обобщение на инструмента за разработка на SPA
След завършване на този урок сте овладели:
- **Архитектура на шаблони:** Повторно използваеми HTML компоненти с динамично рендиране на съдържание
- **Клиентско маршрутизиране:** Управление на URL и навигация без презареждане на страницата
- **Интеграция с браузъра:** Използване на History API и поддръжка на бутоните назад/напред
- **Системи, базирани на събития:** Обработка на навигация и взаимодействия с потребителя
- **Манипулация на DOM:** Клониране на шаблони, смяна на съдържанието и управление на елементи
- **Обработка на грешки:** Гъвкави алтернативи при невалидни маршрути и липсващо съдържание
- **Модели за производителност:** Ефективно зареждане и рендиране на съдържание
**Приложения в реалния свят:** Вашите умения за разработка на SPA са приложими директно към:
- **Модерни уеб приложения:** Разработка с React, Vue, Angular и други рамки
- **Прогресивни уеб приложения:** Офлайн приложения с потребителско изживяване като на приложение
- **Корпоративни табла:** Сложни бизнес приложения с множество изгледи
- **Електронна търговия:** Каталози с продукти, пазарни колички и процедури за поръчка
- **Управление на съдържание:** Динамично създаване и редактиране на съдържание
- **Мобилна разработка:** Хибридни приложения суеб технологии
**Професионални умения, които сте придобили:**
- **Проектирайте** едностранични приложения с правилно разделение на отговорностите
- **Имплементирайте** клиентски системи за маршрутизация, които се мащабират с комплексността на приложението
- **Отстранявайте грешки** в сложни навигационни потоци, използвайки инструменти за разработчици на браузъра
- **Оптимизирайте** производителността на приложението чрез ефективно управление на шаблоните
- **Дизайнирайте** потребителски изживявания, които се усещат като нативни и отзивчиви
**Владеене на концепции за Frontend разработка**:
- **Архитектура на компоненти**: Повторно използваеми UI шаблони и системи за шаблони
- **Синхронизация на състоянието**: Управление на състоянието в URL и история на браузъра
- **Събитиен програмиране**: Обработка на взаимодействия на потребителя и навигация
- **Оптимизация на производителността**: Ефективна манипулация на DOM и зареждане на съдържание
- **Дизайн на потребителско изживяване**: Плавни преходи и интуитивна навигация
**Следващо ниво**: Готови сте да изследвате модерни frontend рамки, усъвършенствано управление на състоянието или да създавате сложни корпоративни приложения!
🌟 **Постижение отключено**: Изградили сте професионална основа на едностранично приложение с модерни архитектурни модели за уеб!
---
## Предизвикателство на GitHub Copilot Agent 🚀
## GitHub Copilot Agent Challenge 🚀
Използвайте режима Agent, за да завършите следното предизвикателство:
Използвайте Agent режима, за да завършите следното предизвикателство:
**Описание:** Подобрете банковото приложение, като имплементирате обработка на грешки и шаблон за страница 404 за невалидни маршрути, подобрявайки потребителското изживяване при навигация към несъществуващи страници.
**Описание:** Подобрете банковото приложение като имплементирате обработка на грешки и шаблон за 404 страница при невалидни маршрути, подобрявайки потребителското изживяване при навигация към несъществуващи страници.
**Задача:** Създайте нов HTML шаблон с идентификатор "not-found", който показва удобна за потребителя страница за грешка 404 със стилове. След това модифицирайте логиката на маршрутизацията в JavaScript, за да показва този шаблон, когато потребителите навигират към невалидни URL адреси, и добавете бутон "Към началната страница", който да води обратно към страницата за вход.
**Задача:** Създайте нов HTML шаблон сid "not-found", който показва приятелска 404 страница с подходящ стил. След това модифицирайте логиката на маршрутизация в JavaScript, за да показва този шаблон при навигация към невалидни URL адреси и добавете бутон "Go Home", който връща към страницата за вход.
Научете повече за [режим Agent](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
Научете повече за [agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
## 🚀 Предизвикателство
Добавете нов шаблон и маршрут за трета страница, която показва кредитите за това приложение.
**Цели на предизвикателството:**
- **Създайте** нов HTML шаблон с подходяща структура на съдържанието
- **Добавете** новия маршрут към конфигурационния обект на маршрутите
- **Включете** навигационни връзки към и от страницата с кредитите
- **Тествайте** дали цялата навигация работи правилно с историята на браузъра
**Цели на предизвикателството:**
- **Създайте** нов HTML шаблон с подходяща структура на съдържанието
- **Добавете** новия маршрут към обекта сконфигурация на маршрутите
- **Включете** навигационни връзки към и от страницата с кредити
- **Проверете**, че цялата навигация работи правилно с историята на браузъра
## Тест след лекцията
## Кратък тест след лекцията
[Тест след лекцията](https://ff-quizzes.netlify.app/web/quiz/42)
[Кратък тест след лекцията](https://ff-quizzes.netlify.app/web/quiz/42)
## Преглед и самостоятелно обучение
## Преглед и самоподготовка
Маршрутизацията е една от изненадващо сложните части на уеб разработката, особено когато уебът преминава от поведение с презареждане на страници към едностранични приложения. Прочетете малко за [как услугата Azure Static Web App](https://docs.microsoft.com/azure/static-web-apps/routes/?WT.mc_id=academic-77807-sagibbon) се справя с маршрутизацията. Можете ли да обясните защо някои от решенията, описани в този документ, са необходими?
Маршрутизацията е една от изненадващо сложните части на уеб разработката, особено с преминаването от поведение на презареждане на страници към презареждане на страници в едностранични приложения. Прочетете малко за [как услугата Azure Static Web App](https://docs.microsoft.com/azure/static-web-apps/routes/?WT.mc_id=academic-77807-sagibbon) обработва маршрутизацията. Можете ли да обясните защо някои от решенията, описани в този документ, са необходими?
**Допълнителни ресурси за обучение:**
- **Разгледайте** как популярни рамки като React Router и Vue Router имплементират маршрутизация от страна на клиента
- **Проучете** разликите между маршрутизацията, базирана на хаш, и маршрутизацията с History API
- **Научете** за рендирането от страна на сървъра (SSR) и как то влияе на стратегиите за маршрутизация
- **Разследвайте** как прогресивните уеб приложения (PWAs) се справят с маршрутизацията и навигацията
**Допълнителни ресурси за учене:**
- **Изследвайте** как популярни рамки като React Router и Vue Router имплементират клиентска маршрутизация
- **Проучете** разликите между маршрутизиране базирано на хеш и маршрутизиране чрез история на API
- **Научете** за серверно рендиране (SSR) и как то влияе на стратегиите за маршрутизация
- **Разгледайте** как Progressive Web Apps (PWAs) боравят с маршрутизация и навигация
## Задача
## Домашна задача
[Подобрете маршрутизацията](assignment.md)
---
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Отказ от отговорност**:
Този документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Не носим отговорност за недоразумения или погрешни интерпретации, произтичащи от използването на този превод.
Този документ е преведен с помощта на AI преводаческа услуга [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи могат да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Не носим отговорност за всякакви недоразумения или неправилни тълкувания, произтичащи от използването на този превод.
- **Минута 3**: Създайте проста функция `updateState()` за контролирани обновявания
- **Минута 4**: Обновете една функция да използва новия модел
- **Минута 5**: Тествайте подобрената предвидимост и възможности за отстраняване на грешки
**Бърз Диагностичен Тест**:
```javascript
// Преди: Разпръснато състояние
let account = null; // Загубено при презареждане!
// След: Централизирано състояние
let state = Object.freeze({ account: null }); // Контролирано и проследимо!
```
**Защо е важно това**: За 5 минути ще усетите преобразяването от хаотично управление на състоянието към предвидими, лесни за отстраняване на грешки модели. Това е основата, която прави сложните приложения поддържани.
## 🗺️ Вашето Обучително Пътуване Към Майсторството на Управлението на Състоянието
```mermaid
journey
title От разпръснато състояние до професионална архитектура
section Диагностика на проблеми
Идентифициране на проблеми със загуба на състояние: 3: You
Разбиране на разпръснати актуализации: 4: You
Признаване на нуждите от архитектура: 6: You
section Централизиране на контрола
Създаване на обединен обект на състоянието: 5: You
Изпълнение на контролирани актуализации: 7: You
Добавяне на непроменяеми модели: 8: You
section Добавяне на персистентност
Изпълнение на localStorage: 6: You
Обработка на сериализация: 7: You
Създаване на непрекъснатост на сесията: 9: You
section Балансиране на свежестта
Решаване на проблема със застаряване на данни: 5: You
Изграждане на системи за обновяване: 8: You
Постигнат оптимален баланс: 9: You
```
**Вашата крайна цел**: В края на този урок ще сте изградили професионална система за управление на състоянието, която обработва запазването, свежестта на данните и предвидими обновявания - същите модели, използвани в продукционни приложения.
## Предварителен Квиз преди Лекцията
[Предварителен квиз преди лекция](https://ff-quizzes.netlify.app/web/quiz/47)
## Въведение
Управлението на състоянието е като навигационната система на космическия кораб Voyager – когато всичко работи гладко, едва забелязвате, че съществува. Но когато нещо се обърка, то става разликата между достигането на междузвездното пространство и загубата в космическата пустота. Вуеб разработката състоянието представлява всичко, което вашето приложение трябва да запомни: статус на вход на потребителя, данни от формуляри, история на навигацията и временни състояния на интерфейса.
Управлението на състоянието е като навигационната система на космическия апарат Voyager – когато всичко работи гладко, едва го забелязваме. Но когато нещо се обърка, това прави разликата между достигането до междузвездното пространство и лутането изгубен в космическата пустота. Вуеб разработката състоянието представлява всичко, което приложението ви трябва да запомни: статус на влизане на потребителя, данни от формуляри, история на навигацията и временни интерфейсни състояния.
Докато вашето банково приложение сее развивало от прост формуляр за вход в по-сложно приложение, вероятно сте се сблъскали с някои общи предизвикателства. Обновете страницата и потребителите се излизат неочаквано. Затворете браузъра и целият напредък изчезва. Дебъгнете проблем и се оказвате, че търсите през множество функции, които модифицират едни и същи данни по различни начини.
Докато вашето банково приложение серазвива от прост формуляр за вход към по-усъвършенствано приложение, вероятно сте срещнали някои често срещани предизвикателства. Опреснявате страницата и потребителите неочаквано се излизат. Затваряте браузъра и целият напредък изчезва. Отстранявате проблем и трябва да търсите в множество функции, които променят едни и същи данни по различен начин.
Това не са признаци на лошо програмиране – това са естествени трудности, които се появяват, когато приложенията достигнат определен праг на сложност. Всеки разработчик се сблъсква с тези предизвикателства, когато приложенията преминават от "доказателство за концепция" към "готово за производство".
Това не са признаци на лошо програмиране – това са естествените растежни болки, които възникват, когато приложенията достигнат определена сложност. Всеки разработчик среща тези предизвикателства, докато приложението му преминава от „доказателство на концепцията“ към „продукт, готов за производство“.
В този урок ще внедрим централизирана система за управление на състоянието, която ще трансформира вашето банково приложение в надеждно, професионално приложение. Ще научите как да управлявате потоците от данни предсказуемо, да запазвате потребителските сесии по подходящ начин и да създавате гладко потребителско изживяване, което изискват съвременните уеб приложения.
В този урок ще реализираме централизирана система за управление на състоянието, която преобразява вашето банково приложение в надеждно, професионално приложение. Ще научите как да управлявате потокa на данни предвидимо, да запазвате сесии на потребители по подходящ начин и да създавате гладко потребителско изживяване, което съвременните уеб приложения изискват.
## Предпоставки
## Предварителни Изисквания
Преди да се потопите в концепциите за управление на състоянието, трябва да имате правилно настроена среда за разработка и основата на вашето банково приложение. Този урок се основава директно на концепциите и кода от предишните части на тази серия.
Преди да се потопите в концепциите за управление на състоянието, ще трябва да сте настроили правилно вашата среда за разработка и да имате основата на банковото приложение на място. Този урок стъпва директно върху концепциите и кода от предишните части на тази серия.
Уверете се, че разполагате със следните компоненти, преди да продължите:
Уверете се, че разполагате със следните компоненти преди да продължите:
**Необходима настройка:**
- Завършете урока за [извличане на данни](../3-data/README.md) - вашето приложение трябва успешно да зарежда и показва данни за акаунта
**Изисквано Настройване:**
- Завършете [урока за извличане на данни](../3-data/README.md) – приложението ви трябва успешно да зарежда и показва данни за акаунта
- Инсталирайте [Node.js](https://nodejs.org) на вашата система за стартиране на бекенд API
- Стартирайте [сървърния API](../api/README.md) локално за обработка на операции с данни за акаунта
- Стартирайте локално [server API](../api/README.md), за да обработва операции с данни за акаунта
**Тестване на вашата среда:**
**Тестване на Средата Ви:**
Проверете дали вашият API сървър работи правилно, като изпълните тази команда в терминала:
```sh
curl http://localhost:5000/api
# -> should return "Bank API v1.0.0" as a result
# -> трябва да върне "Bank API v1.0.0" като резултат
```
**Какво прави тази команда:**
- **Изпраща** GET заявка към вашия локален API сървър
- **Изпраща** GET заявка към локалния ви API сървър
- **Тества** връзката и проверява дали сървърът отговаря
- **Връща** информация за версията на API, ако всичко работи правилно
- **Връща** информация за версията на API, ако всичко работи коректно
## 🧠 Преглед на Архитектурата на Управление на Състоянието
```mermaid
mindmap
root((Управление на състоянието))
Current Problems
Session Loss
Проблеми при презареждане на страница
Влияние от затваряне на браузъра
Проблеми с нулиране на променливи
Scattered Updates
Множество точки на промяна
Предизвикателства при дебъгване
Непредсказуемо поведение
Incomplete Cleanup
Проблеми със състоянието при излизане
Изтичане на памет
Проблеми със сигурността
Centralized Solutions
Unified State Object
Единен източник на истина
Предсказуема структура
Разширима основа
Controlled Updates
Непроменящи се модели
Използване на Object.freeze
Промени базирани на функции
State Tracking
Управление на историята
Видимост при дебъгване
Одит на промените
Persistence Strategies
localStorage Integration
Продължителност на сесията
JSON сериализация
Автоматична синхронизация
Data Freshness
Обновяване от сървъра
Обработка на остарели данни
Оптимизация на баланса
Storage Optimization
Минимални данни
Фокус върху производителността
Съображения за сигурност
```
**Основен Принцип**: Професионалното управление на състоянието балансира предвидимост, запазване и производителност, за да създаде надеждни потребителски изживявания, които се мащабират от прости взаимодействия до сложни работни процеси на приложение.
---
## Диагностика на текущите проблеми със състоянието
## Диагностициране на Настоящите Проблеми със Състоянието
Като Шерлок Холмс, който изследва местопрестъпление, трябва да разберем точно какво се случва в текущата ни имплементация, преди да можем да решим мистерията на изчезващите потребителски сесии.
Като Шерлок Холмс, разглеждащ местопрестъпление, трябва да разберем точно какво се случва в настоящата ни реализация, преди да можем да решим мистерията със изчезващите потребителски сесии.
Нека проведем прост експеримент, който разкрива основните предизвикателства при управлението на състоянието:
Нека направим прост експеримент, който разкрива основните предизвикателства при управлението на състоянието:
**🧪 Опитайте този диагностичен тест:**
1. Влезте в банковото си приложение и отидете на таблото за управление
2. Обновете страницата на браузъра
3. Наблюдавайте какво се случва със статуса на вашия вход
**🧪 Изпробвайте този диагностичен тест:**
1. Влезте в банкното приложение и отидете на таблото за управление
2. Опреснявате страницата в браузъра
3. Наблюдавайте какво се случва със статуса ви на влизане
Ако сте пренасочени обратно към екрана за вход, сте открили класическия проблем с запазването на състоянието. Това поведение се случва, защото текущата ни имплементация съхранява потребителските данни в JavaScript променливи, които се нулират при всяко презареждане на страницата.
Ако бъдете пренасочени обратно към екрана за вход, сте открили класическия проблем със съхранението на състоянието. Това поведение се случва, защото текущата ни реализация запазва потребителските данни в JavaScript променливи, които се нулират при всяко презареждане на страницата.
**Проблеми с текущата имплементация:**
**Проблеми сНастоящата Реализация:**
Простата променлива `account` от нашия [предишен урок](../3-data/README.md) създава три значителни проблема, които засягат както потребителското изживяване, така и поддръжката на кода:
Простата променлива `account` от предишнияни [урок](../3-data/README.md) създава три значителни проблема, които влияят както на потребителския опит, така и на поддръжката на кода:
| Проблем | Техническа причина | Въздействие върху потребителя |
| **Загуба на сесия** | Обновяването на страницата изчиства JavaScript променливите | Потребителите трябва често да се автентифицират |
| **Разпръснати актуализации** | Множество функции модифицират състоянието директно | Дебъгването става все по-трудно |
| **Непълно изчистване** | Излизането не изчиства всички препратки към състоянието | Потенциални проблеми със сигурността и поверителността |
| Проблем | Техническа Причина | Влияние върху Потребителя |
|---------|---------|------------------------|
| **Загуба на Сесия** | При опресняване на страницата JavaScript променливите се изчистват | Потребителите трябва често да се удостоверяват наново |
| **Разпръснати Обновявания** | Множество функции пряко модифицират състоянието | Отстраняването на грешки става все по-трудно |
| **Непълно Изчистване** | Излизането не изчиства всички препратки към състоянието | Потенциални проблеми със сигурността и поверителността |
**Архитектурното предизвикателство:**
**Архитектурното Предизвикателство:**
Както дизайна на Титаник с отделни отделения, който изглеждаше здрав, докато няколко отделения не се наводниха едновременно, решаването на тези проблеми поотделно няма да адресира основния архитектурен проблем. Нуждаем се от цялостно решение за управление на състоянието.
Като дизайна на Титаник с отделни отсеци, който изглежда здрав, докато не се напълнят с вода няколко отсека едновременно, коригирането на тези проблеми поотделно няма да разреши основния архитектурен проблем. Нуждаем се от цялостно решение за управление на състоянието.
> 💡 **Какво всъщност се опитваме да постигнем тук?**
[Управлението на състоянието](https://en.wikipedia.org/wiki/State_management) всъщност се свежда до решаването на два основни въпроса:
1. **Къде са моите данни?**: Проследяване на информацията, която имаме, и откъде идва
2. **Всички ли са на една и съща страница?**: Уверяване, че това, което потребителите виждат, съответства на това, което всъщност се случва
**Нашият план за действие:**
Вместо да се въртим в кръг, ще създадем **централизирана система за управление на състоянието**. Представете си, че имате един наистина организиран човек, който отговаря за всички важни неща:

**Разбиране на този поток от данни:**
- **Централизира** цялото състояние на приложението на едно място
- **Насочва** всички промени в състоянието чрез контролирани функции
[Управлението на състоянието](https://en.wikipedia.org/wiki/State_management) е наистина за решаване на два основни въпроса:
1. **Къде са моите данни?**: Следене каква информация имаме и откъде идва тя
2. **Всички ли са на една и съща страница?**: Да сме сигурни, че това, което потребителите виждат, съответства на действителното състояние
**Нашата Игрова Стратегия:**
Вместо да се лутаме безцелно, ще създадем **централизирана система за управление на състоянието**. Представете си я като един наистина организиран човек, който отговаря за цялата важна информация:

```mermaid
flowchart TD
A[Действие на потребителя] --> B[Обработчик на събития]
B --> C[Функция updateState]
C --> D{Валидация на състоянието}
D -->|Валидно| E[Създаване на ново състояние]
D -->|Невалидно| F[Обработка на грешки]
E --> G[Object.freeze]
G --> H[Обновяване на localStorage]
H --> I[Задействане на обновяване на UI]
I --> J[Потребителят вижда промените]
F --> K[Потребителят вижда грешка]
subgraph "Ниво за управление на състоянието"
C
E
G
end
subgraph "Ниво за съхранение"
H
L[localStorage]
H -.-> L
end
```
**Разбиране на този поток на данни:**
- **Централизира** цялото приложение състояние на едно място
- **Пренасочва** всички промени в състоянието през контролирани функции
- **Осигурява** синхронизация на потребителския интерфейс с текущото състояние
- **Предоставя** ясен, предсказуем модел за управление на данни
- **Предоставя** ясен и предвидим модел за управление на данните
> 💡 **Професионален съвет**: Този урок се фокусира върху основни концепции. За сложни приложения библиотеки като [Redux](https://redux.js.org) предоставят по-напреднали функции за управление на състоянието. Разбирането на тези основни принципи ще ви помогне да овладеете всяка библиотека за управление на състоянието.
> 💡 **Професионален Възглед**: Този урок се фокусира върху основните концепции. За сложни приложения библиотеки като [Redux](https://redux.js.org) предлагат по-напреднали възможности за управление на състоянието. Разбирането на тези основни принципи ще ви помогне да овладеете всяка библиотека за управление на състоянието.
> ⚠️ **Напреднала тема**: Няма да разглеждаме автоматични актуализации на потребителския интерфейс, предизвикани от промени в състоянието, тъй като това включва концепции за [Реактивно програмиране](https://en.wikipedia.org/wiki/Reactive_programming). Помислете за това като отлична следваща стъпка във вашето обучение!
> ⚠️ **Разширена Тема**: Няма да покриваме автоматични UI обновявания, задействани от промени в състоянието, тъй като това включва концепции от [реактивното програмиране](https://en.wikipedia.org/wiki/Reactive_programming). Помислете за това като отлична следваща стъпка в обучението си!
### Задача: Централизиране на структурата на състоянието
### Задача: Централизиране на Структурата на Състоянието
Нека започнем трансформирането на нашето разпръснато управление на състоянието в централизирана система. Тази първа стъпка установява основата за всички подобрения, които следват.
Нека започнем да трансформираме разпръснатото управление на състоянието в централизирана система. Тази първа стъпка създава основата за всички подобрения, които ще последват.
**Стъпка 1: Създаване на централен обект за състояние**
**Стъпка 1: Създаване на Централен Обект за Състояние**
Заменете простото деклариране на `account`:
@ -112,7 +236,7 @@ curl http://localhost:5000/api
let account = null;
```
Със структурирания обект за състояние:
Със структурирания обект за състоянието:
```js
let state = {
@ -120,77 +244,109 @@ let state = {
};
```
**Защо тази промяна е важна:**
**Ето защо тази промяна е важна:**
- **Централизира** всички данни на приложението на едно място
- **Подготвя** структурата за добавяне на повече свойства на състоянието по-късно
- **Създава** ясна граница между състоянието и другите променливи
- **Установява** модел, който семащабира с растежа на приложението
- **Подготвя** структурата за добавяне на още свойства на състоянието по-късно
- **Създава** ясна граница между състояние и други променливи
- **Установява** модел, който мащабира с растежа на приложението
**Стъпка 2: Актуализиране на моделите за достъп до състоянието**
**Стъпка 2: Обновяване на Шаблоните за Достъп до Състоянието**
Актуализирайте вашите функции, за да използват новата структура на състоянието:
Обновете функциите си да използват новата структура на състоянието:
**Във функциите `register()` и `login()`**, заменете:
**Във функциите `register()` и `login()`** заменете:
```js
account = ...
```
С:
с:
```js
state.account = ...
```
**Във функцията `updateDashboard()`**, добавете този ред в началото:
**Във функцията `updateDashboard()`** добавете този ред в началото:
```js
const account = state.account;
```
**Какво постигат тези актуализации:**
- **Запазват** съществуващата функционалност, като подобряват структурата
- **Подготвят** вашия код за по-сложно управление на състоянието
- **Създават** последователни модели за достъп до данни за състоянието
- **Установяват** основата за централизирани актуализации на състоянието
- **Запазват** съществуващата функционалност, като същевременно подобряват структурата
- **Подготвят** кода ви за по-усъвършенствано управление на състоянието
- **Създават** последователни модели за достъп до данните на състоянието
- **Установяват** основата за централизирани обновявания на състоянието
> 💡 **Забележка**: Това преструктуриране не решава веднага проблемите ни, но създава необходимата основа за мощните подобрения, които предстоят!
### 🎯 Педагогическа Проверка: Принципи на Централизацията
> 💡 **Забележка**: Това рефакториране не решава веднага нашите проблеми, но създава основата за мощните подобрения, които предстоят!
**Пауза и Размишление**: Току-що реализирахте основата на централизираното управление на състоянието. Това е ключово архитектурно решение.
## Внедряване на контролирани актуализации на състоянието
**Бърза Самооценка**:
- Можете ли да обясните защо централизираното съхраняване на състоянието в един обект е по-добро от разпръснати променливи?
- Какво би се случило, ако забравите да обновите функцията да използва `state.account`?
- Как този модел подготвя кода ви за по-усъвършенствани функционалности?
С централизирано състояние, следващата стъпка включва установяване на контролирани механизми за модификации на данни. Този подход осигурява предсказуеми промени в състоянието и по-лесно дебъгване.
**Реална Връзка**: Моделът за централизиране, който научихте, е основата на модерни рамки като Redux, Vuex и React Context. Вие изграждате същия архитектурен подход, използван в големи приложения.
Основният принцип прилича на контрол на въздушния трафик: вместо да позволяваме на множество функции да модифицират състоянието независимо, ще насочим всички промени чрез една контролирана функция. Този модел предоставя ясен контрол върху това кога и как се променят данните.
**Въпрос за Размисъл**: Ако трябва да добавите потребителски предпочитания (тема, език) към приложението си, къде бихте ги добавили в структурата на състоянието? Как това би мащабирало?
**Управление на неизменяемо състояние:**
## Реализиране на Контролирани Обновявания на Състоянието
Ще третираме нашия обект `state` като [*неизменяем*](https://en.wikipedia.org/wiki/Immutable_object), което означава, че никога няма да го модифицираме директно. Вместо това, всяка промяна създава нов обект за състояние с актуализираните данни.
След като сме централизирали състоянието, следващата стъпка е да установим контролирани механизми за промени на данните. Този подход осигурява предвидими промени и по-лесно отстраняване на грешки.
Въпреки че този подход може първоначално да изглежда неефективен в сравнение с директните модификации, той предоставя значителни предимства за дебъгване, тестване и поддържане на предсказуемостта на приложението.
Основният принцип наподобява въздушния контрол на полетите: вместо да позволяваме на множество функции самостоятелно да променят състоянието, ще навигираме всички промени през една контролирана функция. Този модел дава ясен преглед кога и как се случват промените.
**Предимства на управлението на неизменяемо състояние:**
**Управление на имутируемото състояние:**
| Предимство | Описание | Въздействие |
|------------|----------|-------------|
| **Предсказуемост** | Промените се случват само чрез контролирани функции | По-лесно дебъгване и тестване |
| **Проследяване на историята** | Всяка промяна в състоянието създава нов обект | Позволява функции за отмяна/възстановяване |
| **Предотвратяване на странични ефекти** | Няма случайни модификации | Предотвратява мистериозни грешки |
| **Оптимизация на производителността** | Лесно откриване на промени в състоянието | Позволява ефективни актуализации на потребителския интерфейс |
Ще третираме обекта `state` като [*имутируем*](https://en.wikipedia.org/wiki/Immutable_object), което означава, че никога не го променяме директно. Вместо това всяка промяна създава нов обект със състоянието с обновените данни.
**Неизменяемост в JavaScript с`Object.freeze()`:**
Въпреки че този подход може първоначално да изглежда по-малко ефективен от директните модификации, той носи големи предимства при отстраняване на грешки, тестване и поддържане на предвидимостта на приложението.
**Предимства на имутируемото управление на състоянието:**
| Полза | Описание | Влияние |
|---------|-------------|--------|
| **Предвидимост** | Промените се случват само чрез контролирани функции | По-лесно отстраняване на грешки и тестване |
| **Проследяване на историята** | Всяка промяна създава нов обект | Позволява функции за отменяне/възстановяване |
| **Предотвратяване на странични ефекти** | Няма случайни промени | Предпазва от мистериозни грешки |
| **Оптимизация на производителността** | Лесно се засича кога състоянието е променено | Позволява ефективни UI обновявания |
**JavaScript имутируемост с`Object.freeze()`:**
JavaScript предоставя [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze), за да предотврати модификации на обекти:
// Any attempt to modify immutableState will throw an error
// Всеки опит за промяна на immutableState ще хвърли грешка
```
**Какво се случва тук:**
- **Предотвратява** директни присвоявания или изтривания на свойства
- **Генерира** изключения при опити за модификация
- **Осигурява** промени в състоянието само чрез контролирани функции
- **Създава** ясен договор за начина, по който може да се актуализира състоянието
> 💡 **Дълбоко разбиране**: Научете за разликата между *повърхностно* и *дълбоко* неизменяеми обекти в [документацията на MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze). Разбирането на това разграничение е от съществено значение за сложни структури на състоянието.
**Разграждане на това, което се случва тук:**
- **Предотвратява** директно присвояване или изтриване на свойства
- **Хвърля** изключения при опити за модификация
- **Осигурява**, че промяната на състоянието трябва да минава през контролирани функции
- **Създава** ясен договор за начина, по който състоянието може да бъде обновявано
> 💡 **Задълбочаване**: Научете за разликата между *повърхностно* и *дълбоко* имутируеми обекти в [документацията на MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze). Разбирането на тази разлика е ключово за сложни структури на състоянието.
@ -204,9 +360,9 @@ function updateState(property, newData) {
}
```
В тази функция създаваме нов обект за състояние и копираме данни от предишното състояние, използвайки [*оператора за разпръскване (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). След това заменяме конкретно свойство на обекта за състояние с новите данни, използвайки [нотацията с квадратни скоби](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` за присвояване. Накрая заключваме обекта, за да предотвратим модификации, използвайки `Object.freeze()`. Засега съхраняваме само свойството `account` в състоянието, но с този подход можете да добавите толкова свойства, колкото са ви необходими.
В тази функция създаваме нов обект със състоянието и копираме данни от предишното състояние с помощта на [*spread (`...`) оператора*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). След това заменяме конкретно свойство на обекта със състоянието с новите данни, използвайки [брадкети за именоване](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` за присвояване. Накрая заключваме обекта, за да предотвратим модификации, като използваме `Object.freeze()`. Засега имаме само свойството `account` в състоянието, но с този подход можете да добавите колкото искате свойства.
Също така ще актуализираме инициализацията на `state`, за да се уверим, че началното състояние също е заключено:
Ще обновим и инициализацията на `state`, за да гарантираме, че началното състояние също е замразено:
```js
let state = Object.freeze({
@ -214,19 +370,19 @@ let state = Object.freeze({
});
```
След това актуализирайте функцията `register`, като замените присвояването `state.account = result;`с:
След това обновете функцията `register`, като замените присвояването `state.account = result;`с:
```js
updateState('account', result);
```
Направете същото с функцията `login`, като замените `state.account = data;`с:
Направете същото в `login` функцията, като замените `state.account = data;`с:
```js
updateState('account', data);
```
Сега ще използваме възможността да поправим проблема с неизчистването на данните за акаунта, когато потребителят кликне върху *Logout*.
Сега ще използваме възможността да отстраним проблема с невъзстановяването на данните за акаунта при натискане на *Изход*.
Опитайте да регистрирате нов акаунт, след това излезте и влезте отново, за да проверите, че всичко все още работи правилно.
> Съвет: можете да проследявате всички промени в състоянието, като добавите `console.log(state)` в края на `updateState()` и отворите конзолата в инструментите за разработчици на браузъра.
## Реализиране на Запазване на Данни
Проблемът със загубата на сесия, който установихме по-рано, изисква решение за запазване на данни, което поддържа състоянието на потребителя между сесиите на браузъра. Това превръща приложението ни от временен опит в надежден, професионален инструмент.
Помислете как атомните часовници поддържат прецизно време дори при прекъсвания на електрозахранването, като съхраняват критичното състояние в нестабилна памет. По същия начин уеб приложенията се нуждаят от постоянни механизми за съхранение, за да запазят важните потребителски данни между сесиите и презарежданията на страницата.
Опитайте да регистрирате нов акаунт, да излезете и да влезете отново, за да проверите дали всичко все още работи правилно.
**Стратегически въпроси за запазването на данни:**
> Съвет: можете да разгледате всички промени в състоянието, като добавите `console.log(state)` в края на `updateState()` и отворите конзолата в инструментите за разработка на браузъра.
Преди да реализирате запазването, обмислете тези критични фактори:
## Внедряване на запазване на данни
| Въпрос | Контекст на Банковото Приложение | Влияние върху Решението |
| **Данните чувствителни ли са?** | Баланс по сметка, история на транзакции | Избирайте сигурни методи за съхранение |
| **Колко дълго трябва да се съхранява?** | Състояние на влизане спрямо временни UI предпочитания | Изберете подходяща продължителност на съхранение |
| **Сървърът нуждае ли се от това?** | Токени за удостоверяване спрямо UI настройки | Определете изискванията за споделяне |
Проблемът със загубата на сесия, който идентифицирахме по-рано, изисква решение за запазване, което да поддържа състоянието на потребителя през сесиите на браузъра. Това трансформира нашето приложение от временно изживяване в надежден, професионален инструмент.
**Опции за съхранение в браузъра:**
Помислете как атомните часовници поддържат прецизно време дори при прекъсвания на захранването, като съхраняват критично състояние в неволатилна памет. По подобен начин уеб приложенията се нуждаят от механизми за запазване на данни, за да съхраняват основни потребителски данни през сесиите на браузъра и обновяванията на страницата.
Съвременните браузъри предлагат няколко механизма за съхранение, всеки предназначен за различни случаи на употреба:
**Стратегически въпроси за запазване на данни:**
**Основни API за съхранение:**
Преди да внедрите запазване, обмислете тези критични фактори:
1. **[`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage)**: Постоянно [ключ/стойност съхранение](https://en.wikipedia.org/wiki/Key%E2%80%93value_database)
- **Запазва** данните между сесиите на браузъра за неопределено време
- **Оцеляват** рестартирания на браузъра и компютъра
- **Ограничен** до конкретния домейн на уебсайта
- **Перфектен** за потребителски предпочитания и състояния на влизане
2. **[`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage)**: Временно съхранение за сесията
- **Функционира** идентично на localStorage по време на активни сесии
- **Изчиства се** автоматично при затваряне на таба в браузъра
- **Идеален** за временни данни, които не трябва да се запазват
| **Данните чувствителни ли са?** | Баланс на акаунта, история на транзакциите | Изберете сигурни методи за съхранение |
| **Колко дълго трябва да се запазят?** | Статус на вход срещу временни UI предпочитания | Изберете подходяща продължителност на съхранение |
| **Сървърът
> 💡 **Разширена опция**: За сложни офлайн приложения с големи набори от данни, обмислете използването на [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Той предоставя пълна база данни на клиентската страна, но изисква по-сложно внедряване.
// Парсиране на JSON низове обратно в обекти при извличане
### Задача: Имплементиране на постоянство с localStorage
**Разбиране на сериализацията:**
- **Конвертира** JavaScript обекти в JSON низове чрез [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify)
- **Възстановява** обекти от JSON чрез [`JSON.parse()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse)
- **Обработва** автоматично сложни вложени обекти и масиви
- **Не работи** с функции, неопределени стойности и циклични препратки
> 💡 **Разширен вариант**: За сложни офлайн приложения с големи набори от данни, разгледайте [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Той предоставя пълна клиентска база данни, но изисква по-сложна имплементация.
### Задача: Имплементиране на постоянство в localStorage
Нека имплементираме постоянство на съхранението, за да останат потребителите вписани, докато не се отпишат изрично. Ще използваме `localStorage`, за да съхраняваме данни за акаунта между сесиите на браузъра.
Нека реализираме постоянно съхранение, така че потребителите да остават влезли, докато не се излязат изрично. Ще използваме `localStorage` за съхранение на данни за акаунта между сесиите в браузъра.
**Стъпка 1: Дефиниране на конфигурация за съхранение**
- **Конвертира** обекта на акаунта в JSON низ за съхранение
- **Запазва** данните, използвайки нашия последователен ключ за съхранение
- **Изпълнява се** автоматично при всяка промяна на състоянието
- **Запазва** данните чрез нашия последователен ключ за съхранение
- **Изпълнява**се автоматично при всяка промяна на състоянието
- **Гарантира**, че съхранените данни винаги са синхронизирани с текущото състояние
> 💡 **Полза за архитектурата**: Тъй като централизирахме всички актуализации на състоянието чрез `updateState()`, добавянето на постоянство изискваше само един ред код. Това демонстрира силата на добрите архитектурни решения!
> 💡 **Архитектурно предимство**: Тъй като централизираме всички обновления на състоянието чрез `updateState()`, добавянето на постоянство изискваше само един ред код. Това показва силата на добрите архитектурни решения!
**Стъпка 3: Възстановяване на състоянието при зареждане на приложението**
Създайте функция за инициализация, която да възстановява запазените данни:
Създайте инициализираща функция за възстановяване на запазените данни:
```js
function init() {
@ -303,7 +518,7 @@ function init() {
updateState('account', JSON.parse(savedAccount));
}
// Our previous initialization code
// Нашият предишен код за инициализация
window.onpopstate = () => updateRoute();
updateRoute();
}
@ -312,48 +527,62 @@ init();
```
**Разбиране на процеса на инициализация:**
- **Извлича** всички предварително запазени данни за акаунта от localStorage
- **Взема** всички предварително запазени данни за акаунта от localStorage
- **Парсира** JSON низа обратно в JavaScript обект
- **Актуализира** състоянието, използвайки нашата контролирана функция за актуализация
- **Обновява** състоянието чрез нашата контролирана функция за обновяване
- **Възстановява** сесията на потребителя автоматично при зареждане на страницата
- **Изпълнявасе** преди актуализациите на маршрута, за да гарантира, че състоянието е налично
- **Изпълнява** се преди ъпдейти на маршрутите, за да осигури наличност на състоянието
**Стъпка 4: Оптимизиране на основния маршрут**
**Стъпка 4: Оптимизиране на стандартния маршрут**
Актуализирайте основния маршрут, за да се възползвате от постоянството:
Обновете дефолтния маршрут, за да се възползва от постоянството:
В`updateRoute()` заменете:
В`updateRoute()`, заменете:
```js
// Replace: return navigate('/login');
// Замени: return navigate('/login');
return navigate('/dashboard');
```
**Защо тази промяна има смисъл:**
- **Използва** ефективно нашата нова система за постоянство
- **Позволява** на таблото да обработва проверките за автентикация
- **Пренасочва** автоматично към вход, ако няма запазена сесия
- **Създава** по-плавно потребителско изживяване
- **Използва** ефективно новата ни система за постоянство
- **Позволява** на таблото при нужда да прави проверки за удостоверяване
- **Пренасочва** към влизане автоматично, ако няма запазена сесия
- **Създава** по-гладко изживяване за потребителя
**Тестване на вашата имплементация:**
1. Впишете се в приложението за банкиране
2. Обновете страницата на браузъра
3. Уверете се, че оставате вписани и на таблото
1. Влезте в банковото си приложение
2. Презаредете страницата в браузъра
3. Проверете дали оставате влезли и сте на таблото
4. Затворете и отворете отново браузъра
5. Върнете се към приложението и потвърдете, че все още сте вписани
5. Върнете се в приложението и потвърдете, че все още сте влезли
🎉 **Постижение отключено**: Успешно сте имплементирали управление на постоянно състояние! Вашето приложение сегасе държи като професионално уеб приложение.
### 🎯 Педагоически контролна точка: Архитектура на постоянството
**Разбиране на архитектурата**: Вие сте реализирали сложен слой на постоянство, който балансира изживяването на потребителя с управлението на сложността на данните.
🎉 **Постижение отключено**: Успешно имплементирахте управление на постоянно състояние! Вашето приложение вече се държи като професионално уеб приложение.
**Основни усвоени концепции**:
- **JSON сериализация**: Преобразуване на сложни обекти в низове за съхранение
- **Автоматична синхронизация**: Промените в състоянието задействат постоянно съхранение
- **Възстановяване на сесията**: Приложенията могат да възстановят потребителския контекст след прекъсвания
- **Централизирано постоянство**: Една функция за обновяване управлява цялото съхранение
## Балансиране на постоянството със свежестта на данните
**Връзка с индустрията**: Този модел на постоянство е фундаментален за Progressive Web Apps (PWA), приложения с офлайн първи подход и съвременни мобилни уеб изживявания. Вие изграждате възможности на продукционно ниво.
Нашата система за постоянство успешно поддържа потребителските сесии, но въвежда ново предизвикателство: остарели данни. Когато множество потребители или приложения модифицират едни и същи данни на сървъра, локално кешираната информация става неактуална.
**Въпрос за размисъл**: Как бихте модифицирали тази система, за да поддържа множество потребителски акаунти на едно устройство? Помислете за поверителността и сигурността.
Тази ситуация наподобява навигаторите викинги, които разчитали както на съхранени звездни карти, така и на текущи наблюдения на небесните тела. Картите предоставяли последователност, но навигаторите се нуждаели от свежи наблюдения, за да се съобразят с променящите се условия. По подобен начин нашето приложение се нуждае както от постоянно потребителско състояние, така и от актуални данни от сървъра.
## Балансиране на постоянството с актуалността на данните
**🧪 Откриване на проблема със свежестта на данните:**
Нашата система за постоянство успешно поддържа потребителските сесии, но въвежда ново предизвикателство: застаряване на данните. Когато множество потребители или приложения модифицират едни и същи данни на сървъра, локалната кеширана информация остарява.
1. Впишете се в таблото, използвайки акаунта `test`
2. Изпълнете тази команда в терминала, за да симулирате транзакция от друг източник:
Тази ситуация е подобна на викингски навигатори, които са разчитали едновременно на съхранени звездни карти и актуални астрономически наблюдения. Картите предоставяха постоянство, но навигаторите имаха нужда от свежи наблюдения, за да отчитат променящите се условия. По същия начин приложението ни се нуждае както от постоянно потребителско състояние, така и от актуални сървърни данни.
**🧪 Откриване на проблема със застаряването на данни:**
1. Влезте в таблото с акаунта `test`
2. Изпълнете следната команда в терминал, за да симулирате транзакция от друг източник:
- **Показва** как localStorage може да стане "остарял" (неактуален)
- **Симулира** реални сценарии, при които данните се променят извън вашето приложение
- **Разкрива** напрежението между постоянството и свежестта на данните
- **Показва** как локалното съхранение може да стане „застаряло“ (неактуално)
- **Симулира** реални ситуации, при които данните се променят извън приложението
- **Разкрива** напрежението между постоянството и актуалността на данните
**Предизвикателството със старите данни:**
**Проблемът със застаряването на данните:**
| Проблем | Причина | Влияние върху потребителя |
|---------|---------|---------------------------|
| **Остарели данни** | localStorage никога не изтича автоматично | Потребителите виждат неактуална информация |
| **Промени на сървъра** | Други приложения/потребители модифицират същите данни | Несъответстващи изгледи между платформите |
| **Кеш срещу реалност** | Локалният кеш не съответства на състоянието на сървъра | Лошо потребителско изживяване и объркване |
|---------|--------|--------------------------|
| **Остарели данни** | localStorage никога не изтича автоматично | Потребителите виждат остаряла информация |
| **Промени на сървъра** | Други приложения/потребители модифицират същите данни | Несъответстващи изгледи на различни платформи |
| **Кеш спрямо реалност** | Локалният кеш не съвпада със състоянието на сървъра | Лошо потребителско изживяване и объркване |
**Стратегия за решение:**
Ще имплементираме модел "обновяване при зареждане", който балансира предимствата на постоянството с нуждата от свежи данни. Този подход поддържа плавното потребителско изживяване, като същевременно гарантира точност на данните.
Ще реализираме модел „презареждане при зареждане“, който балансира ползите на постоянството с нуждата от свежи данни. Този подход запазва гладкото потребителско изживяване като същевременно гарантира точност на данните.
```mermaid
sequenceDiagram
participant U as Потребител
participant A as Приложение
participant L as локалноСъхранение
participant S as Сървър
U->>A: Отваря приложението
A->>L: Зареди запазено състояние
L-->>A: Върни кеширани данни
A->>U: Покажи потребителския интерфейс незабавно
A->>S: Извличане на актуални данни
S-->>A: Върни текущите данни
A->>L: Обнови кеша
A->>U: Обнови интерфейса с актуални данни
```
### Задача: Имплементиране на система за обновяване на данни
Ще създадем система, която автоматично извлича свежи данни от сървъра, като същевременно запазва предимствата на нашето управление на постоянното състояние.
Ще създадем система, която автоматично извлича свежи данни от сървъра, като същевременно поддържа предимствата на нашето управление на постоянно състояние.
**Стъпка 1: Създаване на обновител на данни за акаунта**
**Стъпка 1: Създайте функция за обновяване на данните на акаунта**
```js
async function updateAccountData() {
@ -404,15 +649,15 @@ async function updateAccountData() {
}
```
**Разбиране на логиката на тази функция:**
- **Проверява** дали потребителят е вписан (state.account съществува)
- **Пренасочва** към изход, ако не е намерена валидна сесия
- **Извлича** свежи данни за акаунта от сървъра, използвайки съществуващата функция `getAccount()`
- **Обработва** грешки от сървъра, като излиза от невалидни сесии
- **Актуализира** състоянието със свежи данни, използвайки нашата контролирана система за актуализация
- **Задейства** автоматичното постоянство на localStorage чрез функцията`updateState()`
**Логика на тази функция:**
- **Проверява** дали потребителят е влязъл (съществува state.account)
- **Пренасочва** към излизане, ако няма валидна сесия
- **Извлича** свежи данни за акаунта от сървъра чрез съществуващата функция `getAccount()`
- **Обработва** грешки от сървъра като излизане при невалидни сесии
- **Обновява** състоянието със свежи данни чрез контролирания ни механизъм
- **Задейства** автоматичното съхранение в localStorage чрез`updateState()`
**Стъпка 2: Създаване на обработващ за обновяване на таблото**
**Стъпка 2: Създайте обработчик за обновяване на таблото**
```js
async function refresh() {
@ -422,14 +667,14 @@ async function refresh() {
```
**Какво постига тази функция за обновяване:**
- **Координира** процеса на обновяване на данните и актуализацията на потребителския интерфейс
- **Изчаква** зареждането на свежи данни преди актуализацията на дисплея
- **Координира** процеса на обновяване и ъпдейт на UI
- **Изчаква** зареждането на свежите данни преди обновяване на изгледа
- **Гарантира**, че таблото показва най-актуалната информация
- **Поддържа** чисто разделение между управлението на данни и актуализациите на потребителския интерфейс
- **Поддържа** ясно разделяне между управление на данни и UI ъпдейти
**Стъпка 3: Интеграция с системата за маршрути**
**Стъпка 3: Интегрирайте с маршрутната система**
Актуализирайте конфигурацията на маршрута, за да задействате автоматично обновяване:
Обновете конфигурацията на маршрутите, за да задействате обновяването автоматично:
```js
const routes = {
@ -439,68 +684,125 @@ const routes = {
```
**Как работи тази интеграция:**
- **Изпълнява** функцията за обновяване всеки път, когато се зарежда маршрутът на таблото
- **Гарантира**, че свежите данни винаги се показват, когато потребителите навигират към таблото
- **Поддържа** съществуващата структура на маршрута, като добавя свежест на данните
- **Осигурява** последователен модел за инициализация, специфична за маршрута
- **Изпълнява** функцията за обновяване всеки път при зареждане на маршрута на таблото
- **Гарантира**, че винаги се показват свежи данни при навигация към таблото
- **Запазва** съществуващата структура на маршрутите, като добавя актуалност на данните
- **Осигурява** последователен модел за инициализация специфична за маршрут
**Тестване на вашата система за обновяване на данни:**
1. Впишете се в приложението за банкиране
1. Влезте в банковото си приложение
2. Изпълнете командата curl от по-рано, за да създадете нова транзакция
3. Обновете страницата на таблото или навигирайте извън и обратно
4. Уверете се, че новата транзакция се появява веднага
3. Презаредете страницата на таблото или навигирайте далеч и обратно
4. Проверете, че новата транзакция се появява веднага
🎉 **Постигнат перфектен баланс**: Вашето приложение комбинира плавното изживяване на постоянното състояние с точността на свежите сървърни данни!
## 📈 Вашата времева линия на овладяване на управлението на състоянието
```mermaid
timeline
title Професионално Пътуване в Управлението на Състоянието
section Разпознаване на Проблема
State Issues Diagnosis
: Идентифициране на проблеми с изгубени сесии
: Разбиране на проблемите с разпокъсани актуализации
: Признаване на архитектурни нужди
section Основи на Архитектурата
Centralized State Design
: Създаване на унифицирани обекти на състоянието
: Прилагане на контролирани модели на актуализация
: Установяване на имутируеми принципи
Predictable Updates
: Усвояване на използването на Object.freeze()
: Изграждане на системи удобни за дебъгване
: Създаване на мащабируеми модели
section Майсторство в Съхранение
localStorage Integration
: Обработка на JSON сериализация
: Прилагане на автоматична синхронизация
: Създаване на продължителност на сесията
Data Freshness Balance
: Справяне с предизвикателствата на остаряване на данните
: Изграждане на механизми за обновяване
: Оптимизация на производителността спрямо точността
section Професионални Модели
Production-Ready Systems
: Прилагане на обработка на грешки
: Създаване на поддържана архитектура
: Следване на най-добрите практики в индустрията
Advanced Capabilities
: Готовност за интеграция с рамки
: Подготвен за сложни състояния
: Основи за реално времеви функции
```
**🎓 Ключово постижение**: Успешно сте изградили пълна система за управление на състоянието, използвайки същите принципи, които движат Redux, Vuex и други професионални библиотеки. Тези модели се мащабират от прости приложения до корпоративни системи.
🎉 **Постигнато перфектно равновесие**: Вашето приложение вече комбинира плавното изживяване на постоянното състояние с точността на свежите данни от сървъра!
**🔄 Следващо ниво възможности**:
- Готови за овладяване на рамки за управление на състоянието (Redux, Zustand, Pinia)
- Подготвени за внедряване на реалновременни функции с WebSockets
- Оборудвани за изграждане на офлайн първи Progressive Web Apps
- Основи за напреднали модели като машини на състояния и наблюдатели
## Предизвикателство на GitHub Copilot Agent 🚀
## Предизвикателство GitHub Copilot Agent 🚀
Използвайте режим Agent, за да завършите следното предизвикателство:
Използвайте режим Агент, за да завършите следното предизвикателство:
**Описание:** Имплементирайте цялостна система за управление на състоянието с функционалност за отменяне/възстановяване за приложението за банкиране. Това предизвикателство ще ви помогне да практикувате напреднали концепции за управление на състоянието, включително проследяване на историята на състоянието, неизменни актуализации и синхронизация на потребителския интерфейс.
**Описание:** Имплементирайте пълно управление на състоянието с функции за отмяна и повторно изпълнение за банковото приложение. Това предизвикателство ще ви помогне да упражните усъвършенствани концепции за управление на състоянието, включително проследяване на история, иммутабилни обновявания и синхронизация с интерфейса.
**Задача:** Създайте подобрена система за управление на състоянието, която включва: 1) Масив за история на състоянието, който проследява всички предишни състояния, 2) Функции за отменяне и възстановяване, които могат да връщат предишни състояния, 3) Бутони в потребителския интерфейс за операции отменяне/възстановяване на таблото, 4) Максимален лимит на историята от 10 състояния, за да се предотвратят проблеми с паметта, и 5) Правилно изчистване на историята, когато потребителят се отпише. Уверете се, че функционалността за отменяне/възстановяване работи с промените в баланса на акаунта и се запазва между обновяванията на браузъра.
**Подсказка:** Създайте разширена система за управление на състоянието, която включва: 1) Масив с история на състоянията, който следи всички предишни състояния, 2) Функции за undo и redo, които могат да връщат към предишни състояния, 3) Бутоните за undo/redo в UI на таблото, 4) Максимален лимит на историята от 10 състояния, за да сеизбегнат проблеми с паметта, и 5) Правилно изчистване на историята при излизане на потребителя. Уверете се, че undo/redo функционалността работи с промени в баланса по акаунта и се запазва при презареждания на браузъра.
Научете повече за [режим Agent](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
Научете повече за [agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
## 🚀 Предизвикателство: Оптимизация на съхранението
Вашата имплементация вече ефективно обработва потребителските сесии, обновяването на данни и управлението на състоянието. Въпреки това, обмислете дали текущият ни подход оптимално балансира ефективността на съхранението с функционалността.
Вашата реализация вече ефективно управлява потребителски сесии, обновяване на данни и управление на състоянието. Въпреки това, обмислете дали настоящият подход оптимално балансира ефективността на съхранение с функционалността.
Както шахматните майстори разграничават основните фигури от тези, които могат да бъдат пожертвани, ефективното управление на състоянието изисква идентифициране на данните, които трябва да се запазят, спрямо тези, които винаги трябва да се извличат свежи от сървъра.
Подобно на шахматистите, които разпознават съществените фигури и излишните пешки, ефективното управление на състоянието изисква да се идентифицира кои данни трябва да бъдат постоянни и кои винаги да са свежи от сървъра.
**Анализ на оптимизацията:**
Оценете текущата си имплементация на localStorage и обмислете тези стратегически въпроси:
- Каква е минималната информация, необходима за поддържане на автентикацията на потребителя?
- Кои данни се променят достатъчно често, че локалното кеширане предоставя малка полза?
Оценете текущата си имплементация на localStorage и разгледайте тези стратегически въпроси:
- Кояе минималната информация, необходима за поддържане на потребителската автентикация?
- Кои данни се променят толкова често, че локалното кеширане дава малко полза?
- Как оптимизацията на съхранението може да подобри производителността, без да влошава потребителското изживяване?
Този тип архитектурен анализ отличава опитните разработчици, които разглеждат както функционалността, така и ефективността в решенията си.
**Стратегия за имплементация:**
- **Идентифицирайте** основните данни, които трябва да се запазят (вероятно само идентификацията на потребителя)
- **Модифицирайте** вашата имплементация на localStorage, за да съхранява само критични данни за сесията
- **Гарантирайте**, че свежи данни винаги се зареждат от сървъра при посещения на таблото
- **Тествайте**, че вашият оптимизиран подход поддържа същото потребителско изживяване
- **Идентифицирайте** съществените данни, които трябва да се съхраняват (вероятно само идентификация на потребителя)
- **Модифицирайте** localStorage имплементацията, за да съхранява само критични данни за сесията
- **Осигурете** винаги зареждане на свежи данни от сървъра при посещение на таблото
- **Тествайте**, че оптимизираният ви подход запазва същото потребителско изживяване
**Разширено разглеждане:**
- **Сравнете** компромисите между съхранението на пълни данни за акаунта и само на токени за автентикация
- **Документирайте** вашите решения и аргументи за бъдещите членове на екипа
**Разширено съображение:**
- **Сравнете** плюсовете и минусите на съхранение на пълни данни за акаунта спрямо само автентикационните токени
- **Документирайте** решенията и мотивите си за бъдещите членове на екипа
Това предизвикателство ще ви помогне да мислите като професионален разработчик, който обмисля както потребителското изживяване, така и ефективността на приложението. Отделете време да експериментирате с различни подходи!
Това предизвикателство ще ви помогне да мислите като професионален разработчик, който отчита както изживяването на потребителя, така и ефективността на приложението. Отделете време да експериментирате с различни подходи!
## Тест след лекцията
## Квиз след лекцията
[Тест след лекцията](https://ff-quizzes.netlify.app/web/quiz/48)
[Квиз след лекцията](https://ff-quizzes.netlify.app/web/quiz/48)
## Задание
## Задача
[Имплементирайте диалог за "Добавяне на транзакция"](assignment.md)
[Имплементирайте диалог „Добавяне на транзакция“](assignment.md)
Ето примерен резултат след завършване на заданието:
Ето примерен резултат след завършване на задачата:


---
**Отказ от отговорност**:
Този документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за каквито и да било недоразумения или погрешни интерпретации, произтичащи от използването на този превод.
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Отказ от отговорност**:
Този документ е преведен с помощта на услуга за автоматичен превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматичните преводи могат да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация е препоръчително професионално човешко превеждане. Ние не носим отговорност за каквито и да е недоразумения или неправилни тълкувания, произтичащи от използването на този превод.
След завършване на това задание, вашето банково приложение трябва да има напълно функционална функция "Добавяне на транзакция", която изглежда и работи професионално:


В този проект ще научите как да създадете измислена банка. Тези уроци включват инструкции за това как да изградите уеб приложение, да създадете маршрути, да изградите форми, да управлявате състоянието и да извличате данни от API, от който можете да получите данните на банката.
# Използване на редактор за код: Овладяване на VSCode.dev
Помните ли в *Матрицата*, когато Нео трябваше да се свърже с огромен компютърен терминал, за да влезе в дигиталния свят? Днешните инструменти за уеб разработка саточно обратното – невероятно мощни възможности, достъпни отвсякъде. VSCode.dev е редактор за код, базиран на браузър, който предоставя професионални инструменти за разработка на всяко устройство с интернет връзка.
Спомняте ли си в *Матрицата*, когато Нео трябваше да се свърже с огромен компютърен терминал, за да получи достъп до дигиталния свят? Днешните инструменти за уеб разработка сасъвсем обратното – невероятно мощни възможности, достъпни отвсякъде. VSCode.dev е редактор за код в браузър, който предоставя професионални инструменти за разработка на всяко устройство с интернет връзка.
Точно както печатната преса направи книгите достъпни за всички, а не само за монасите в манастирите, VSCode.dev демократизира програмирането. Можете да работите по проекти от библиотечен компютър, училищна лаборатория или където и да имате достъп до браузър. Без инсталации, без ограничения от типа "Трябва ми специфична настройка".
Точно както печатарската преса направи книгите достъпни за всички, а не само за монаси, VSCode.dev демократизира програмирането. Можете да работите върху проекти от компютър в библиотека, училищна лаборатория или навсякъде, където имате достъп до браузър. Без инсталации, без ограничения като „Имам нужда от моя конкретен набор“.
До края на този урок ще разберете как да навигирате в VSCode.dev, да отваряте GitHub хранилища директно в браузъра си и да използвате Git за контрол на версиите – умения, на които професионалните разработчици разчитат ежедневно.
Към края на този урок ще разберете как да навигирате в VSCode.dev, да отваряте директно GitHub хранилища в браузъра си и да използвате Git за контрол на версиите – всички умения, на които професионалните разработчици разчитат ежедневно.
## ⚡ Какво Можете да Направите в Следващите 5 Минути
**Бърз старт за заети разработчици**
```mermaid
flowchart LR
A[⚡ 5 минути] --> B[Посетете vscode.dev]
B --> C[Свържете GitHub акаунт]
C --> D[Отворете който и да е репозитори]
D --> E[Започнете редактиране незабавно]
```
- **Минута 1**: Отидете на [vscode.dev](https://vscode.dev) – не е необходима инсталация
- **Минута 2**: Влезте с GitHub, за да свържете хранилищата си
- **Минута 3**: Опитайте трика с URL: променете `github.com` на `vscode.dev/github` в произволен URL на репо
- **Минута 4**: Създайте нов файл и гледайте как автоматично работи оцветяването на синтаксиса
- **Минута 5**: Направете промяна и я комитнете чрез панела на Source Control
**Бърз тестови URL**:
```
# Transform this:
github.com/microsoft/Web-Dev-For-Beginners
# Into this:
vscode.dev/github/microsoft/Web-Dev-For-Beginners
```
**Защо е важно**: За 5 минути ще усетите свободата на програмиране навсякъде с професионални инструменти. Това представлява бъдещето на разработката – достъпно, мощно и моментално.
## 🗺️ Вашето учебно пътуване през облачната разработка
```mermaid
journey
title От локална настройка до майсторство в облачното разработване
section Разбиране на платформата
Открийте уеб-базирано редактиране: 4: You
Свържете сес екосистемата на GitHub: 6: You
Овладейте навигацията в интерфейса: 7: You
section Умения за управление на файлове
Създавайте и организирайте файлове: 5: You
Редактирайте с подсветка на синтаксиса: 7: You
Навигирайте структури на проекти: 8: You
section Майсторство върху версия контрол
Разберете интеграцията с Git: 6: You
Практикувайте комит работни потоци: 8: You
Овладейте модели за сътрудничество: 9: You
section Професионална персонализация
Инсталирайте мощни разширения: 7: You
Конфигурирайте средата за разработка: 8: You
Създавайте лични работни потоци: 9: You
```
**Вашата крайна цел**: Към края на този урок ще сте овладели професионална облачна среда за разработка, която работи от всяко устройство, позволявайки ви да програмирате със същите инструменти като разработчиците в големите технологични компании.
## Какво ще научите
След като преминем през това заедно, ще можете:
След като преминем през урока, ще можете да:
- Навигирате VSCode.dev като у дома си – намирайте всичко нужно без да се губите
- Отваряте произволно GitHub хранилище в браузъра и да започнете редактиране незабавно (това е истинска магия!)
- Използвате Git, за да следите промените си и да запазвате напредъка като професионалист
- Ускорите работата си с разширения, които правят кодирането по-бързо и забавно
- Създавате и организирате файлове за проекти с увереност
- Да навигирате в VSCode.dev като в свой втори дом – да намирате всичко, което ви е нужно, без да се губите
- Да отваряте всяко GitHub хранилище в браузъра си и да започнете да го редактирате веднага (това е доста магично!)
- Да използвате Git, за да следите промените си и да запазвате напредъка си като професионалист
- Да подобрите редактора си с разширения, които правят програмирането по-бързо и забавно
- Да създавате и организирате файлове за проекти с увереност
## Какво ще ви трябва
## Какво ви е необходимо
Изискванията са ясни:
Изискванията са прости:
- Безплатен [GitHub акаунт](https://github.com) (ще ви преведем през създаването, ако е нужно)
- Основни умения суеб браузъри
- Урокът GitHub Basics предлага полезен фон, но не е задължителен
- Безплатен [GitHub акаунт](https://github.com) (ще ви помогнем да го създадете, ако е необходимо)
- Основни познания за уеб браузъри
- Урокът "Основи на GitHub" предоставя полезна информация, въпреки че не е задължителен
> 💡 **Нов в GitHub?** Създаването на акаунт е безплатно и отнема минути. Както библиотечната карта дава достъп до книги по целия свят, така и GitHub акаунтът отваря врати към хранилища с код из целия интернет.
> 💡 **Нов в GitHub?** Създаването на акаунт е безплатно и отнема само няколко минути. Точно както библиотечната карта ви дава достъп до книги по целия свят, GitHub акаунтът ви отваря врати към хранилища с код в интернет.
## 🧠 Преглед на екосистемата за облачна разработка
## Защо са важни редакторите за код, базирани на уеб
```mermaid
mindmap
root((VSCode.dev Мастерство))
Platform Benefits
Accessibility
Независимост от устройството
Без необходимост от инсталация
Моментални актуализации
Универсален достъп
Integration
Връзка с GitHub
Синхронизация на хранилище
Запазване на настройки
Готовност за сътрудничество
Development Workflow
File Management
Структура на проекта
Подчертаване на синтаксис
Редактиране с множество табове
Функции за автоматично записване
Version Control
Интеграция с Git
Работни процеси за комитване
Управление на клонове
Проследяване на промени
Customization Power
Extensions Ecosystem
Инструменти за продуктивност
Поддръжка на езици
Тема опции
Персонализирани преки пътища
Environment Setup
Лични предпочитания
Конфигурация на работна среда
Интеграция на инструменти
Оптимизация на работния процес
Professional Skills
Industry Standards
Контрол на версиите
Качество на кода
Сътрудничество
Документация
Career Readiness
Работа от разстояние
Облачна разработка
Екипни проекти
Отворен код
```
**Основен принцип**: Облачните среди за разработка представляват бъдещето на програмирането – предоставяне на професионални инструменти, които са достъпни, колаборативни и независими от платформа.
Преди интернет учените от различни университети не можеха лесно да споделят изследванията си. След това се появи ARPANET през 60-те години, свързвайки компютри на големи разстояния. Редакторите за код, базирани на уеб, следват същия принцип – правят мощни инструменти достъпни, независимо от вашето местоположение или устройство.
## Защо са важни редакторите за код в уеб
Редакторът за код служи като работно пространство за разработка, където пишете, редактирате и организирате файлове с код. За разлика от обикновените текстови редактори, професионалните редактори за код предоставят оцветяване на синтаксиса, откриване на грешки и функции за управление на проекти.
Преди интернет, учените в различни университети не можеха лесно да споделят изследвания. След това дойде ARPANET през 60-те години, свързващ компютри на разстояние. Уеб базираните редактори следват същия принцип – правят мощни инструменти достъпни независимо от физическото ви местоположение или устройство.
VSCode.dev предоставя тези възможности директно в браузъра ви:
Редакторът за код е вашето работно пространство за разработка, където пишете, редактирате и организирате кодовите файлове. За разлика от обикновените текстови редактори, професионалните редактори осигуряват оцветяване на синтаксиса, откриване на грешки и управление на проекти.
VSCode.dev предоставя тези възможности в браузъра ви:
**Предимства на редактирането в уеб:**
| Функция | Описание | Практическа полза |
|---------|-------------|----------|
| **Платформена независимост** | Работи на всяко устройство с браузър | Работете от различни компютри безпроблемно |
| **Без необходимост от инсталация** | Достъп чрез уеб URL | Избягвайте ограниченията за инсталиране на софтуер |
| **Автоматични актуализации** | Винаги работи с най-новата версия | Достъп до нови функции без ръчни актуализации |
| **Интеграция с хранилища** | Директна връзка с GitHub | Редактирайте код без управление на локални файлове |
| **Независимост от платформа** | Работи на всяко устройство с браузър | Работете безпроблемно от различни компютри |
| **Без нужда от инсталация** | Достъп през уеб URL | Пропуснете ограниченията за инсталиране на софтуер |
| **Автоматични ъпдейти** | Винаги работи с най-новата версия | Достъп до нови функции без ръчни ъпдейти |
| **Интеграция с хранилища** | Директна връзка с GitHub | Редактирайте код без локално управление на файлове |
**Практически последици:**
- Непрекъснатост на работата в различни среди
- Консистентен интерфейс, независимо от операционната система
- Незабавни възможности за сътрудничество
- Намалени изисквания за локално съхранение
- Продължаване на работа през различни среди
- Последователен интерфейс без значение от ОС
- Моментални възможности за колаборация
- Намалени локални изисквания за съхранение
## Разглеждане на VSCode.dev
Точно както лабораторията на Мария Кюри съдържаше сложно оборудване в сравнително простичко пространство, VSCode.dev съчетава професионални инструменти за разработка в интерфейс на браузър. Това уеб приложение предоставя същата основна функционалност като настолните редактори за код.
Точно както лабораторията на Мари Кюри съдържаше сложна апаратура в сравнително простичко пространство, VSCode.dev събира професионални инструменти за разработка в браузърния интерфейс. Това уеб приложение предоставя същата основна функционалност като десктоп редакторите за код.
Започнете, като отворите [vscode.dev](https://vscode.dev) в браузъра си. Интерфейсът се зарежда без изтегляния или системни инсталации – директно приложение на принципите на облачните изчисления.
### Свързване на вашия GitHub акаунт
Точно както телефонът на Александър Греъм Бел свързва отдалечени места, свързването на вашия GitHub акаунт обединява VSCode.dev с вашите хранилища с код. Когато бъдете подканени да влезете с GitHub, препоръчително е да приемете тази връзка.
Точно както телефонът на Александър Греъм Бел свързваше отдалечени места, свързването на вашия GitHub акаунт свързва VSCode.dev с вашите хранилища с код. Когато бъдете подканени да влезете с GitHub, препоръчително е да приемете това свързване.
**Интеграцията с GitHub предоставя:**
- Директен достъп до вашите хранилища в редактора
- Синхронизирани настройки и разширения на различни устройства
- Оптимизиран процес на запазване в GitHub
**Интеграцията с GitHub осигурява:**
- Директен достъп до хранилищата ви в редактора
- Синхронизирани настройки и разширения между устройствата
- Оптимизиран процес на запис в GitHub
- Персонализирана среда за разработка
### Запознаване с новото ви работно пространство
### Запознаване свашето ново работно пространство
След като всичко се зареди, ще видите красиво подредено работно пространство, което е проектирано да ви помогне да се фокусирате върху най-важното – вашия код!
След зареждането ще видите чисто и приветливо работно пространство, предназначено да ви държи фокусирани върху най-важното – вашия код!


**Ето вашето ръководство за ориентация:**
- **Лента за активност** (тази лента отляво): Вашата основна навигация с Explorer 📁, Търсене 🔍, Контрол на източника 🌿, Разширения 🧩 и Настройки ⚙️
- **Странична лента** (панелът до нея): Променя се, за да ви показва релевантна информация според избраното
- **Зона за редактиране** (голямото пространство в средата): Тук се случва магията – вашата основна зона за програмиране
**Ето обиколката на околността:**
- **Лента с активности** (ляво): Основната навигация с Explorer 📁, Търсене 🔍, Source Control 🌿, Разширения 🧩 и Настройки ⚙️
- **Страничен панел** (до нея): Променя се, за да ви покаже релевантна информация според избора ви
- **Редакторска зона** (голямото пространство в средата): Тук се случва магията –главната ви зона за кодиране
**Отделете момент да разгледате:**
- Кликнете върху иконите в лентата за активност и вижте какво прави всяка от тях
- Забележете как страничната лента се актуализира, за да показва различна информация – доста удобно, нали?
- Изгледът Explorer (📁) вероятно ще бъде мястото, където ще прекарвате най-много време, така че се запознайте с него
**Отделете момент и разгледайте:**
- Кликнете върху иконите в лентата с активности и вижте какво прави всяка от тях
- Забележете как страничният панел се обновява, за да покаже различна информация – доста яко, нали?
- Представата Explorer (📁) най-вероятно ще е мястото, където ще прекарвате повечето време, свикнете с него
```mermaid
flowchart TB
subgraph "Архитектура на интерфейса VSCode.dev"
A[Лента с дейности] --> B[Прегледач 📁]
A --> C[Търсене 🔍]
A --> D[Контрол на изходния код 🌿]
A --> E[Разширения 🧩]
A --> F[Настройки ⚙️]
B --> G[Дърво на файловете]
C --> H[Намери и замени]
D --> I[Състояние на Git]
E --> J[Пазар за разширения]
F --> K[Конфигурация]
L[Странична лента] --> M[Панел на контекста]
N[Област на редактора] --> O[Кодови файлове]
P[Терминал/Изход] --> Q[Команден ред]
end
```
## Отваряне на GitHub хранилища
Преди интернет изследователите трябваше физически да пътуват до библиотеки, за да получат достъп до документи. GitHub хранилищата работят по подобен начин – те са колекции от код, съхранявани дистанционно. VSCode.dev елиминира традиционната стъпка за изтегляне на хранилища на локалната машина преди редактиране.
Преди интернет, изследователите трябваше физически да пътуват до библиотеки, за да достъпят документи. GitHub хранилищата работят подобно – те са колекции от код, съхранявани отдалечено. VSCode.dev елиминира традиционната стъпка на изтегляне на хранилища на локалната ви машина преди редактиране.
Тази възможност позволява незабавен достъп до всяко публично хранилище за преглед, редактиране или принос. Ето два метода за отваряне на хранилища:
Тази възможност дава незабавен достъп до всяко публично хранилище за преглед, редактиране или принос. Ето два начина за отваряне на хранилища:
### Метод 1: Лесният начин с кликване
### Метод 1: Начинът с посочване и кликване
Това е идеално, когато започвате от нулата във VSCode.dev и искате да отворите конкретно хранилище. Лесно и подходящо за начинаещи:
Подходящ е, когато започвате пресен в VSCode.dev и искате да отворите конкретно хранилище. Ясен и приятелски за начинаещи:
**Ето как да го направите:**
1. Отидете на [vscode.dev](https://vscode.dev), ако все още не сте там
2. Потърсете бутона "Open Remote Repository" на началния екран и го натиснете
1. Отидете на [vscode.dev](https://vscode.dev), ако още не сте там
2. Потърсете бутона "Open Remote Repository" на началния екран и натиснете


3. Поставете URL адреса на всяко GitHub хранилище (опитайте този: `https://github.com/microsoft/Web-Dev-For-Beginners`)
4. Натиснете Enter и вижте магията!
3. Поставете произволен URL на GitHub хранилище (опитайте този: `https://github.com/microsoft/Web-Dev-For-Beginners`)
4. Натиснете Enter и гледайте магията да се случи!
**Професионален съвет - Пряк път с Command Palette:**
**Про съвет – клавишна комбинация за Command Palette:**
Искате ли да се почувствате като магьосник в програмирането? Опитайте този клавишен пряк път: Ctrl+Shift+P (или Cmd+Shift+P на Mac), за да отворите Command Palette:
Искате да се почувствате като вълшебник в кодирането? Опитайте клавишната комбинация: Ctrl+Shift+P (или Cmd+Shift+P на Mac) да отворите Command Palette:

**Command Palette е като търсачка за всичко, което можете да направите:**
- Напишете "open remote" и тя ще намери отварящия инструмент за хранилища за вас
- Запомня хранилищата, които сте отваряли наскоро (много удобно!)
- След като свикнетес нея, ще се чувствате като светкавичен програмист
- Това е като версията на VSCode.dev на "Хей, Сири, но за програмиране"
**Command Palette е като търсачка за всичко, което може дасе направи:**
- Напишете "open remote" и ще ви намери функцията за отваряне на хранилища
- Запомня хранилищата, които сте отваряли наскоро (супер удобно!)
- След като свикнете, ще се чувствате, че кодирате със светкавична скорост
- Основно това е версията на VSCode.dev на „Хей Сири“, но за кодиране
### Метод 2: Техника с модификация на URL
### Метод 2: Техника за модификация на URL
Точно както HTTP и HTTPS използват различни протоколи, но запазват една и съща структура на домейна, VSCode.dev използва модел на URL адрес, който отразява системата за адресиране на GitHub. Всеки URL адрес на GitHub хранилище може да бъде модифициран, за да се отвори директно във VSCode.dev.
Точно както HTTP и HTTPS използват различни протоколи, но запазват структурата на домейна, VSCode.dev използва URL модел, който отразява адресната система на GitHub. Всеки GitHub URL може да бъде променен за директно отваряне в VSCode.dev.
**Модел за трансформация на URL:**
**Шаблон за трансформация на URL:**
| Тип хранилище | URL на GitHub | URL на VSCode.dev |
@ -136,220 +260,380 @@ VSCode.dev предоставя тези възможности директно
**Изпълнение:**
- Заменете `github.com`с`vscode.dev/github`
- Запазете всички останали компоненти на URL адреса непроменени
- Запазете всички останали компоненти на URL без промяна
- Работи с всяко публично достъпно хранилище
- Осигурява незабавен достъп за редактиране
- Предоставя незабавен достъп за редактиране
> 💡 **Съвет, който променя живота**: Запазете в отметките си версиите на VSCode.dev на любимите си хранилища. Аз имам отметки като "Редактиране на моето портфолио" и "Поправка на документация", които ме отвеждат директно в режим на редактиране!
> 💡 **Променящ живота съвет**: Запазете в отметки VSCode.dev версиите на любимите си хранилища. Имам отметки като "Edit My Portfolio" и "Fix Documentation", които ме водят директно в режим на редактиране!
**Кой метод да използвате?**
- **Интерфейсният начин**: Чудесен, когато изследвате или не можете да си спомните точните имена на хранилищата
- **Интерфейсният начин**: Страхотен, когато разглеждате или не помните точното име на хранилището
- **Трикът с URL**: Перфектен за светкавичен достъп, когато знаете точно къде отивате
### 🎯 Педагогическа проверка: Достъп до облачна разработка
**Пауза и размисъл**: Току-що научихте два метода за достъп до хранилища с код през уеб браузър. Това представлява фундаментална промяна в начина, по който работи разработката.
**Бърза самооценка**:
- Можете ли да обясните защо редактирането през уеб изключва традиционното „настройване на среда за разработка“?
- Какви предимства дава техниката за модификация на URL в сравнение с локално клониране чрез git?
- Как този подход променя начина, по който бихте допринасяли за проекти с отворен код?
**Връзка с реалния свят**: Големи компании като GitHub, GitLab и Replit изградиха своите платформи за разработка около тези принципи фокусирани върху облака. Вие учите същите работни процеси, използвани от професионални екипи по цял свят.
**Предизвикателен въпрос**: Как облачната разработка може да промени начина, по който се преподава програмирането в училищата? Помислете за изискванията към устройствата, управлението на софтуер и възможностите за сътрудничество.
## Работа с файлове и проекти
Сега, когато сте отворили хранилище, нека започнем да създаваме! VSCode.dev ви предоставя всичко необходимо, за да създавате, редактирате и организирате файловете си с код. Мислете за него като за вашата дигитална работилница – всеки инструмент е точно там, където ви е нужен.
Сега, когато имате отворено хранилище, нека започнем с изграждане! VSCode.dev ви предоставя всичко необходимо, за да създавате, редактирате и организирате файловете си с код. Мислете за него като за вашата дигитална работилница – всички инструменти са точно там, където имате нужда.
Нека се потопим в ежедневните задачи, които ще съставляват по-голямата част от вашия работен процес.
Нека се потопим в ежедневните задачи, които ще формират основата на вашия работен процес при кодирането.
### Създаване на нови файлове
Точно както организирането на чертежи в офиса на архитект, създаването на файлове във VSCode.dev следва структуриран подход. Системата поддържа всички стандартни типове файлове за уеб разработка.
Подобно на организирането на чертежи в офиса на архитект, създаването на файлове във VSCode.dev следва структурирана логика. Системата поддържа всички стандартни файлови формати за уеб разработка.
**Процес на създаване на файлове:**
**Процес на създаване на файл:**
1. Навигирайте до целевата папка в страничната лента Explorer
2. Задръжте курсора върху името на папката, за да се появи иконата "Нов файл" (📄+)
1. Навигирайте до целевата папка в страничния панел Explorer
2. Задръжте курсора върху името на папката, за да се появи иконата „Нов файл“ (📄+)
3. Въведете името на файла, включително подходящото разширение (`style.css`, `script.js`, `index.html`)
4. Натиснете Enter, за да създадете файла


**Конвенции за именуване:**
**Правила за именуване:**
- Използвайте описателни имена, които показват предназначението на файла
- Включете разширения на файловете за правилно оцветяване на синтаксиса
- Следвайте последователни модели на именуване в проектите
- Използвайте малки букви и тирета вместо интервали
- Включвайте разширенията на файловете за правилно оцветяване на синтаксиса
- Следвайте последователни модели за именуване в проектите
- Ползвайте малки букви и тирета вместо интервали
### Редактиране и запазване на файлове
### Редактиране и записване на файлове
Тук започва истинското забавление! Редакторът на VSCode.dev епълен с полезни функции, които правят програмирането гладко и интуитивно. Това е като да имате наистина умен асистент за писане, но за код.
Тук започва истинското забавление! Редакторът на VSCode.dev енатъпкан с полезни функции, които правят кодирането плавно и интуитивно. Като да имате много умен помощник по писане, но за код.
**Вашият работен процес за редактиране:**
1. Кликнете върху всеки файл в Explorer, за да го отворите в основната зона
2. Започнете да пишете и вижте как VSCode.dev ви помага с цветове, предложения и откриване на грешки
3. Запазете работата си с Ctrl+S (Windows/Linux) или Cmd+S (Mac) – въпреки че автоматичното запазване също работи!
1. Кликнете върху който и да е файл в Explorer, за да го отворите в основната зона
2. Започнете да пишете и гледайте как VSCode.dev ви помага с цветове, предложения и откриване на грешки
3. Запазвайте работата си с Ctrl+S (Windows/Linux) или Cmd+S (Mac) – въпреки че имате и автоматично записване!


**Готините неща, които се случват, докато програмирате:**
- Вашият код се оцветява красиво, за да е лесен за четене
- VSCode.dev предлага допълнения, докато пишете (като автокорекция, но много по-умна)
- Открива грешки и пропуски, преди дори да запазите
- Можете да имате отворени множество файлове в раздели, точно както в браузър
- Всичко се запазва автоматично във фонов режим
**Готините неща, които се случват докато кодирате:**
- Вашият код се оцветява красиво, така че да е лесен за четене
- VSCode.dev предлага допълнения докато пишете (като автокорекция, но много по-умна)
- Хваща правописни и логически грешки още преди да запишете
- Можете да имате отворени множество файлове на табове, както в браузър
- Всичко се записва автоматично на заден план
> ⚠️ **Бърз съвет**: Въпреки че автоматичното запазване ви пази, натискането на Ctrl+S или Cmd+S все още е добра практика. Това незабавно запазва всичко и активира някои допълнителни полезни функции като проверка за грешки.
> ⚠️ **Бърз съвет**: Макар и авто-записът да ви пази, свикнете да натискате Ctrl+S или Cmd+S редовно. Той веднага записва всичко и активира допълнителни полезни функции, като проверка за грешки.
### Контрол на версиите с Git
Точно както археолозите създават подробни записи на слоевете на разкопките, Git следи промените в кода ви с времето. Тази система запазва историята на проекта и ви позволява да се върнете към предишни версии, когато е необходимо. VSCode.dev включва интегрирана функционалност на Git.
Подобно на това, как археолозите създават подробни записи на слоевете при разкопки, Git проследява промените във вашия код във времето. Тази система съхранява история на проекта и ви позволява да връщате по-стари версии при нужда. VSCode.dev включва интегрирана Git функционалност.
**Интерфейс за контрол на източника:**
**Интерфейс за Source Control:**
1. Достъпете панела Source Control чрез иконата 🌿 в лентата за активност
2. Променените файлове се появяват в секцията "Changes"
3. Цветното кодиране показва типовете промени: зелено за добавки, червено за изтривания
1. Достъп до панела за Source Control чрез иконата 🌿 в лентата с активности
2. Променените файлове се появяват в секцията „Changes“
3. Цветовото кодиране показва видовете промени: зелен за добавки, червен за изтривания


**Запазване на работата ви (процес на commit):**
**Записване на работата (процес на комит):**
```mermaid
flowchart TD
A[Make changes to files] --> B[View changes in Source Control]
B --> C[Stage changes by clicking +]
C --> D[Write descriptive commit message]
D --> E[Click checkmark to commit]
E --> F[Changes pushed to GitHub]
A[Направете промени във файловете] --> B[Прегледайте промените в Source Control]
B --> C[Подгответе промените, като кликнете +]
C --> D[Напишете описателно съобщение за комит]
D --> E[Кликнете върху отметката, за да комитирате]
E --> F[Промените са изпратени към GitHub]
```
**Ето вашия стъпка по стъпка процес:**
- Кликнете върху иконата "+" до файловете, които искате да запазите (това ги "стейджва")
- Проверете дали сте доволни от всички стейджнати промени
```mermaid
stateDiagram-v2
[*] --> Modified: Редактирай файлове
Modified --> Staged: Натисни + за подготовка
Staged --> Modified: Натисни - за отмяна на подготовката
- Кликнете върху бутона с отметка, за да запазите всичко в GitHub
- Ако промените мнението си за нещо, иконата за отмяна ви позволява да изхвърлите промените
**Писане на добри commit съобщения (по-лесно е, отколкото си мислите!):**
- Просто опишете какво сте направили, като "Добавяне на контактна форма" или "Поправка на счупена навигация"
- Дръжте го кратко и ясно – мислете за дължина на туит, а не за есе
- Започнете с действия като "Добавяне", "Поправка", "Актуализация" или "Премахване"
- **Добри прим
- Всяко разширение показва оценки, брой изтегляния и реални отзиви от потребители
- Получавате екранни снимки и ясни описания за това какво прави всяко разширение
- Дръжте го кратко и ясно – мислете за дължина като на туит, а не есе
- Започвайте с глаголи като "Добави", "Поправи", "Обнови" или "Премахни"
- **Добри примери**: "Добави адаптивно навигационно меню", "Поправи проблеми с мобилния изглед", "Обнови цветовете за по-добра достъпност"
> 💡 **Бърза навигационна подсказка**: Използвайте менюто хамбургер (☰) в горния ляв ъгъл, за да се върнете бързо към вашето GitHub хранилище и да видите направените комити онлайн. Това е като портал между вашата среда за редакция и дома на проекта ви в GitHub!
## Подобряване на функционалността с разширения
Точно както работилницата на майстор съдържа специализирани инструменти за различни задачи, VSCode.dev може да се персонализира с разширения, които добавят специфични възможности. Тези плъгини, разработени от общността, адресират често срещани нужди като форматиране на код, жив преглед и подобрена интеграция с Git.
Маркетплейсът за разширения съдържа хиляди безплатни инструменти, създадени от разработчици по целия свят. Всяко разширение решава конкретни предизвикателства в работния процес, позволявайки ви да изградите персонализирана развойна среда, съобразена с вашите конкретни потребности и предпочитания.
```mermaid
mindmap
root((Екосистема от разширения))
Essential Categories
Производителност
Live Server
Auto Rename Tag
Bracket Pair Colorizer
GitLens
Кодово качество
Prettier
ESLint
Spell Checker
Error Lens
Поддръжка на езици
HTML CSS Support
JavaScript ES6
Python Extension
Markdown Preview
Теми и UI
Dark+ Modern
Material Icon Theme
Peacock
Rainbow Brackets
Discovery Methods
Популярни класации
Download Counts
User Ratings
Recent Updates
Community Reviews
Препоръки
Workspace Suggestions
Language-based
Workflow-specific
Team Standards
```
### Намерете перфектните си разширения
Маркетплейсът за разширения е много добре организиран, така че няма да се загубите, докато търсите това, което ви трябва. Той е проектиран да ви помогне да откриете както конкретни инструменти, така и интересни неща, за които дори не сте знаели!
**Как да отворите маркетплейса:**
1. Кликнете върху иконата Разширения (🧩) в лентата с дейности
2. Разгледайте или търсете нещо конкретно
3. Кликнете върху всичко, което ви се струва интересно, за да научите повече
| **Инсталирани** | Разширения, които вече сте добавили | Вашият личен набор от инструменти за кодиране |
| **Популярни** | Любими на масата | Това, на което повечето разработчици се доверяват |
| **Препоръчани** | Умни предложения за вашия проект | Полезните препоръки на VSCode.dev |
**Как разглеждането е лесно:**
- Всяко разширение показва рейтинги, брой изтегляния и реални отзиви от потребители
- Получавате скрийншоти и ясни описания на функциите му
- Всичко е ясно обозначено с информация за съвместимост
- Предлагат се подобни разширения, за да можете да сравните опциите
- Предлагат се подобни разширения, за да можете да сравните опции
### Инсталиране на разширения (Супер лесно е!)
Добавянето на нови функции към вашия редактор е толкова просто, колкото натискането на един бутон. Разширенията се инсталират за секунди и започват да работят веднага – без рестартиране, без чакане.
Добавянето на нови възможности към редактора ви е толкова просто, колкото кликване на бутон. Разширенията се инсталират за секунди и започват работа веднага – без рестартиране и без чакане.
**Ето какво трябва да направите:**
1. Потърсете това, което искате (опитайте да потърсите "live server" или "prettier")
2. Кликнете върху това, което ви изглежда добре, за да видите повече подробности
3. Прочетете какво прави и проверете оценките
1. Потърсете това, което искате (опитайте с "live server" или "prettier")
2. Кликнете върху разширение, което ви харесва, за да видите повече подробности
3. Прочетете какво прави и разгледайте рейтингите
4. Натиснете синия бутон "Install" и сте готови!

- Разширението се изтегля и автоматично се настройва
- Новите функции се появяват веднага в интерфейса ви
- Всичко започва да работи незабавно (сериозно, толкова е бързо!)
- Разширението се изтегля и настройва автоматично
- Новите функции веднага се появяват във вашия интерфейс
- Всичко започва да работи мигновено (наистина е толкова бързо!)
- Ако сте влезли в профила си, разширението се синхронизира на всички ваши устройства
**Някои разширения, които бих препоръчал за начало:**
- **Live Server**: Вижте как вашият уебсайт се обновява в реално време, докато пишете код (това е магия!)
- **Prettier**: Автоматично прави вашия код чист и професионален
- **Auto Rename Tag**: Променете един HTML таг и неговият партньор също се обновява
- **Bracket Pair Colorizer**: Оцветява скобите, за да не се изгубите
- **GitLens**: Подобрява функциите на Git с много полезна информация
**Някои разширения, които бих препоръчал да започнете с:**
- **Live Server**: Вижте вашия уебсайт дасе обновява в реално време, докато кодирате (магично е!)
- **Prettier**: Прави кода чист и професионален автоматично
- **Auto Rename Tag**: Променете един HTML таг и неговият партньор се обновява автоматично
- **Bracket Pair Colorizer**: Цветово маркира скобите, за да не се губите никога
- **GitLens**: Подсилва вашите Git функциис много полезна информация
### Персонализиране на вашите разширения
Повечето разширения идват с настройки, които можете да промените, за да работят точно както ви харесва. Помислете за това като за настройване на седалката и огледалата в кола – всеки има своите предпочитания!
Повечето разширения идват със настройки, които може да променяте, за да работят точно както ви харесва. Помислете за това като регулиране на седалката и огледалата в кола – всеки си има предпочитания!
**Настройване на разширенията:**
**Как да нагласите настройките на разширение:**
1. Намерете инсталираното разширение в панела Extensions
1. Намерете инсталираното разширение в панела Разширения
2. Потърсете малката икона на зъбно колело (⚙️) до името му и кликнете върху нея
3. Изберете "Extension Settings" от падащото меню
3. Изберете "Extension Settings" от менюто
4. Настройте нещата, докато се почувствате комфортно с вашия работен процес

**Често срещани неща, които може да искате да настроите:**
- Как се форматира вашият код (табове срещу интервали, дължина на реда и т.н.)
**Често срещани неща, които може да коригирате:**
- Как се форматира вашият код (таби срещу интервали, дължина на реда и т.н.)
- Кои клавишни комбинации задействат различни действия
- С кои типове файлове трябва да работи разширението
- Включване или изключване на специфични функции, за да запазите нещата чисти
- С кои файлови типове разширението трябва да работи
- Включване или изключване на определени функции, за да е по-чисто
### Организиране на вашите разширения
### Поддържайте разширенията си организирани
Докато откривате повече интересни разширения, ще искате да поддържате колекцията си подредена и работеща гладко. VSCode.dev прави управлението на разширенията много лесно.
Докато откривате нови страхотни разширения, ще искате да поддържате колекцията си подредена и работеща гладко. VSCode.dev прави това много лесно за управление.
**Опции за управление на разширенията:**
| Какво можете да направите | Когае полезно | Съвет |
| Какво можете да направите | Когае полезно | Полезен съвет |
|--------|---------|----------|
| **Деактивиране** | Тестване дали дадено разширение причинява проблеми | По-добро от деинсталиране, ако може да искате да го върнете |
| **Деинсталиране** | Пълно премахване на разширения, които не ви трябват | Поддържа вашата среда чиста и бърза |
| **Актуализиране** | Получаване на най-новите функции и поправки на грешки | Обикновено се случва автоматично, но си струва да проверите |
| **Деактивиране** | Тествайте дали дадено разширение причинява проблеми | По-добре от деинсталиране, ако може да искате да го върнете |
| **Деинсталиране** | Премахване на ненужни разширения | Поддържа средата ви чиста и бърза |
| **Обновяване** | Получаване на нови функции и поправки | Обикновено се случва автоматично, но е добре да проверявате |
**Как аз обичам да управлявам разширения:**
- На всеки няколко месеца преглеждам инсталираните и махам тези, които не използвам
- Поддържам разширенията актуализирани, за да имам най-новите подобрения и поправки за сигурност
- Ако нещо забавя, временно деактивирам разширения, за да видя дали някое от тях е виновник
- Чета бележките за обновяване при големи ъпдейти – понякога има нови яки функции!
> ⚠️ **Съвет за производителността**: Разширенията са страхотни, но прекалено много могат да забавят нещата. Фокусирайте се върху тези, които истински улесняват живота ви, и не се страхувайте да махнете неизползваните.
### 🎯 Педагогическа проверка: Персонализиране на развойната среда
**Разбиране на архитектурата**: Научихте как да персонализирате професионална развойна среда чрез общностно създадени разширения. Това отразява начина, по който екипите в предприятия изграждат стандартизирани инструментални вериги.
**Как аз обичам да управлявам разширенията:**
- На всеки няколко месеца преглеждам какво съм инсталирал и премахвам всичко, което не използвам
- Поддържам разширенията актуализирани, за да получавам най-новите подобрения и поправки на сигурността
- Ако нещо изглежда бавно, временно деактивирам разширения, за да видя дали някое от тях е причината
- Чета бележките за актуализация, когато разширенията получават големи обновления – понякога има страхотни нови функции!
**Основни усвоени концепции**:
- **Откриване на разширения**: Намиране на инструменти, които решават конкретни разработвачески задачи
- **Конфигуриране на средата**: Персонализиране на инструменти според лични или екипни предпочитания
- **Оптимизация на представянето**: Балансиране на функционалността с производителността на системата
- **Сътрудничество в общността**: Използване на инструменти, създадени от глобалната разработваческа общност
**Връзка с индустрията**: Екосистемите на разширения поддържат големи развойни платформи като VS Code, Chrome DevTools и модерни IDE. Разбирането как да оценявате, инсталирате и конфигурирате разширения е съществено за професионалните работни процеси.
**Въпрос за размисъл**: Как бихте подходили към настройването на стандартизирана развойна среда за екип от 10 разработчици? Обмислете консистентността, производителността и индивидуалните предпочитания.
## 📈 Вашата времева линия за овладяване на разработката в облак
```mermaid
timeline
title Професионално пътуване в облачното развитие
section Основи на платформата
Разбиране на облачното разработване
: Усвояване на концепциите за уеб базирано редактиране
: Свързване на модели за интеграция с GitHub
: Навигиране в професионални интерфейси
section Майсторство в работния процес
Управление на файлове и проекти
: Създаване на организирани проектни структури
: Майсторство на предимствата на синтактичното осветяване
: Работа с работни процеси за редактиране на множество файлове
Интеграция на контрол на версиите
: Разбиране на визуализацията на Git
: Практикуване на стандарти за съобщения при комити
: Майсторство на работните процеси за проследяване на промени
section Персонализиране на средата
Екосистема от разширения
: Откриване на разширения за производителност
: Конфигуриране на предпочитания за разработка
: Оптимизиране на производителността спрямо функционалността
Професионална настройка
: Изграждане на последователни работни процеси
: Създаване на многократно използваеми конфигурации
: Установяване на стандарти за екипа
section Готовност за индустрията
Облачно-предпочитано разработване
: Усвояване на практики за отдалечено разработване
: Разбиране на съвместни работни процеси
: Изграждане на платформа-независими умения
Професионални практики
: Следване на индустриалните стандарти
: Създаване на поддържани работни процеси
: Подготовка за екипна среда
```
**🎓 Етап на завършване**: Успешно сте овладели разработка в облак, използвайки същите инструменти и работни процеси, които професионалните разработчици в големи технологични компании използват. Тези умения представляват бъдещето на софтуерната разработка.
> ⚠️ **Съвет за производителност**: Разширенията са страхотни, но твърде много от тях могат да забавят работата. Фокусирайте се върху тези, които наистина улесняват живота ви, и не се страхувайте да деинсталирате тези, които никога не използвате.
**🔄 Възможности за следващо ниво**:
- Готови сте да изследвате напреднали облачни платформи за разработка (Codespaces, GitPod)
- Подготвени сте да работите в разпределени развойни екипи
- Оборудвани сте да допринасяте за отворен софтуер по света
- Полагате основите за съвременни DevOps и практики за непрекъсната интеграция
## Предизвикателство с GitHub Copilot Agent 🚀
## Предизвикателство GitHub Copilot Agent 🚀
Както структурираният подход на NASA за космически мисии, това предизвикателство включва систематично приложение на уменията от VSCode.dev в цялостен работен процес.
Подобно на структурирания подход, който NASA използва за космически мисии, това предизвикателство включва систематично прилагане на уменията във VSCode.dev в пълен работен процес.
**Цел:** Демонстрирайте уменията си с VSCode.dev, като създадете цялостен работен процес за уеб разработка.
**Цел:** Демонстрирайте уменияс VSCode.dev чрез изграждане на цялостен работен процес за уеб разработка.
**Изисквания за проекта:** С помощта на режим Agent, изпълнете следните задачи:
1. Направете fork на съществуващо хранилище или създайте ново
2. Създайте функционална структура на проект с HTML, CSS и JavaScript файлове
3. Инсталирайте и конфигурирайте три разширения за подобряване на разработката
4. Практикувайте контрол на версиите с описателни съобщения за commit
5. Експериментирайте със създаване и модификация на feature branch
**Изисквания за проекта:** С помощта на Agent режим, изпълнете следните задачи:
1. Форкнете съществуващо хранилище или създайте ново
2. Създайте функционална структура на проектас HTML, CSS и JavaScript файлове
3. Инсталирайте и конфигурирайте три разширения, които подобряват разработката
4. Практикувайте контрол на версиите с описателни commit съобщения
5. Експериментирайте със създаване и модифициране на feature клонове
6. Документирайте процеса и наученото в README.md файл
Това упражнение обединява всички концепции на VSCode.dev в практичен работен процес, който може да бъде приложен към бъдещи проекти за разработка.
Това упражнение обединява всички концепции на VSCode.dev в практичен работен процес, който можете да приложите към бъдещи проекти.
Научете повече за [режим Agent](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
Научете повече за [agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) тук.
## Задача
Време е да изпробвате тези умения в реална практика! Имам проект, който ще ви позволи да упражните всичко, което разгледахме: [Създайте уебсайт за резюме с VSCode.dev](./assignment.md)
Време е да изпробвате тези умения на практика! Имам един проект, с който ще практикувате всичко, което разгледахме: [Създайте уебсайт с автобиография, използвайки VSCode.dev](./assignment.md)
Тази задача ще ви преведе през процеса на създаване на професионален уебсайт за резюме изцяло в браузъра. Ще използвате всички функции на VSCode.dev, които разгледахме, и в края ще имате както страхотен уебсайт, така и солидна увереност в новия си работен процес.
Тази задача ще ви преведе през създаване на професионален уебсайт с автобиография изцяло в браузъра. Ще използвате всички функции на VSCode.dev, които разгледахме, и накрая ще имате както страхотен сайт, така и увереност в новия си работен процес.
## Продължавайте да изследвате и развивате уменията си
Вече имате солидна основа, но има още много интересни неща за откриване! Ето някои ресурси и идеи за усъвършенстване на вашите умения с VSCode.dev:
Вече имате солидна основа, но има още много интересни неща за откриване! Ето няколко ресурса и идеи за повишаване на вашите VSCode.dev умения:
**Официални документи, които си струва да запазите:**
- [Документация за VSCode Web](https://code.visualstudio.com/docs/editor/vscode-web?WT.mc_id=academic-0000-alfredodeza) – Пълно ръководство за редактиране в браузър
- [GitHub Codespaces](https://docs.github.com/en/codespaces) –За когато искате още повече мощност в облака
**Официална документация, която си заслужава да добавите в отметки:**
- [VSCode Web Documentation](https://code.visualstudio.com/docs/editor/vscode-web?WT.mc_id=academic-0000-alfredodeza) – Пълно ръководство за редактиране в браузър
- [GitHub Codespaces](https://docs.github.com/en/codespaces) –За когато искате още повече сила в облака
**Интересни функции за експериментиране:**
- **Клавишни комбинации**: Научете комбинациите, които ще ви направят истински кодиращ нинджа
- **Настройки на работното пространство**: Настройте различни среди за различни типове проекти
- **Мулти-root работни пространства**: Работете върху няколко хранилища едновременно (много удобно!)
- **Интеграция на терминала**: Достъп до инструменти за команден ред директно в браузъра
**Яки функции за експериментиране:**
- **Клавишни комбинации**: Научете бутоните, които ще ви направят програмиращ нинджа
- **Настройки на работната среда**: Конфигурирайте различни среди за различни типове проекти
- **Мултирут работни пространства**: Работете с няколко репозитория едновременно (много удобно!)
- **Интеграция с терминала**: Достъп до командния ред директно в браузъра
**Идеи за практика:**
- Включете се в някои проекти с отворен код и допринасяйте, използвайки VSCode.dev – това е чудесен начин да се отблагодарите!
- Изпробвайте различни разширения, за да намерите идеалната си конфигурация
- Създайте шаблони за проекти за типовете сайтове, които най-често изграждате
- Практикувайте Git работни процеси като създаване на клонове и обединяване – тези умения са златни за екипни проекти
- Включете се в проекти с отворен код и допринасяйте, използвайки VSCode.dev –страхотен начин да дадете обратно!
- Изпробвайте различни разширения, за да намерите перфектните за вас
- Създайте шаблони за проекти за видовете сайтове, които правите най-често
- Практикувайте Git работни процеси като branching и merging – тези умения са злато в екипни проекти
---
**Вие овладяхте разработката в браузър!** 🎉 Както изобретяването на преносими инструменти позволи на учените да провеждат изследвания в отдалечени места, VSCode.dev ви позволява професионално кодиране от всяко устройство с интернет връзка.
**Вие овладяхте разработката в браузър!** 🎉 Както изобретяването на преносими инструменти позволи на учените да изследват отдалечени места, така и VSCode.dev ви дава възможност за професионално кодиране от всяко устройство с интернет връзка.
Тези умения отразяват текущите практики в индустрията– много професионални разработчици използват облачни среди за разработка заради тяхната гъвкавост и достъпност. Вие научихте работен процес, който може да сеадаптира както за индивидуални проекти, така и за големи екипни сътрудничества.
Тези умения отразяват настоящите индустриални практики– много професионални разработчици използват облачни среди заради гъвкавостта и достъпността им. Вие научихте работен процес, който може да семащабира както за индивидуални проекти, така и за големи екипи.
Приложете тези техники към следващия си проект за разработка! 🚀
Прилагайте тези техники в следващия си проект! 🚀
---
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Отказ от отговорност**:
Този документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Не носим отговорност за недоразумения или погрешни интерпретации, произтичащи от използването на този превод.
Този документ е преведен с помощта на AI преводаческа услуга [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на оригиналния език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Не носим отговорност за каквито и да е недоразумения или неправилни тълкувания, възникнали от използването на този превод.
4. **Напишете** съобщение за комит: "Добавяне на начална HTML структура"
5. **Кликнете** "Commit new file", за да запазите промените


**Ето какво постигате с тази начална настройка:**
- **Създавате** правилна HTML5 структура на документа със семантични елементи
@ -104,7 +104,7 @@ CO_OP_TRANSLATOR_METADATA:
✅ **Индикатор за успех**: Трябва да видите файловете на проекта си в страничната лента Explorer и `index.html`, достъпен за редактиране в основната област на редактора.


**Какво ще видите в интерфейса:**
- **Странична лента Explorer**: **Показва** файловете и структурата на папките на вашето хранилище
@ -448,7 +448,7 @@ li:before {
**Незабавни резултати след инсталацията:**
След като CodeSwing е инсталиран, ще видите предварителен преглед на живо на вашия уебсайт за автобиография, който се появява в редактора. Това ви позволява да видите точно как изглежда вашият сайт, докато правите промени.


**Разбиране на подобрения интерфейс:**
- **Разделен изглед**: **Показва** вашия код от едната страна и предварителния преглед от другата
Научете основите на уеб разработката с нашия 12-седмичен изчерпателен курс, предоставен от Microsoft Cloud Advocates. Във всеки от 24-те урока се потапяте в JavaScript, CSS и HTML чрез практическа работа по проекти като терариуми, разширения за браузъри и космически игри. Включете сес викторини, дискусии и практически задачи. Подобрете уменията си и оптимизирайте усвояването на знания с нашата ефективна проектно-базирана педагогика. Започнете своето кодиращо пътешествие още днес!
Научете основите на уеб разработката с нашия 12-седмичен подробен курс, създаден от Microsoft Cloud Advocates. Всяка от 24-те лекции разглежда JavaScript, CSS и HTML чрез практически проекти като терариуми, разширения за браузър и космически игри. Участвайте в тестове, дискусии и практически задачи. Подобрете уменията си и оптимизирайте запаметяването на знанията си с нашата ефективна проектно-ориентирана методология. Започнете своето пътешествие в програмирането още днес!
Присъединете се към общността Azure AI Foundry в Discord
[](https://discord.com/invite/ByRwuEEgH4)
Присъединете се към Discord общността Azure AI Foundry
Следвайте тези стъпки, за да започнете да използвате тези ресурси:
**Ако желаете да бъдат добавени допълнителни преводи, списъкът с поддържани езици е [тук](https://github.com/Azure/co-op-translator/blob/main/getting_started/supported-languages.md)**
> Това хранилище включва над 50 езикови превода, което значително увеличава размера за изтегляне. За да клонирате без преводи, използвайте sparse checkout:
> git sparse-checkout set --no-cone '/*' '!translations' '!translated_images'
> ```
> Това ви предоставя всичко необходимо за завършване на курса с много по-бързо изтегляне.
[](https://open.vscode.dev/microsoft/Web-Dev-For-Beginners)
**Ако желаете да се добавят допълнителни езици за превод, те са изброени [тук](https://github.com/Azure/co-op-translator/blob/main/getting_started/supported-languages.md)**
#### 🧑🎓 _Студент ли сте?_
Посетете [**страницата за студенти**](https://docs.microsoft.com/learn/student-hub/?WT.mc_id=academic-77807-sagibbon), където ще намерите ресурси за начинаещи, студентски пакети и дори начини да получите безплатен ваучер за сертификат. Това е страницата, която трябва да запазите и да проверявате редовно, тъй като съдържанието се обновява ежемесечно.
Посетете [страницата Student Hub](https://docs.microsoft.com/learn/student-hub/?WT.mc_id=academic-77807-sagibbon), където ще намерите ресурси за начинаещи, студентски пакети и дори възможности за получаване на безплатен сертификат. Това е страницата, която трябва да добавите в отметки и да проверявате от време на време, тъй като съдържанието се променя месечно.
### 📣 Съобщение - Нови предизвикателства с режим Agent на GitHub Copilot!
### 📣 Обявление - Нови предизвикателства в GitHub Copilot Agent режим за завършване!
Добавено е ново предизвикателство, потърсете "GitHub Copilot Agent Challenge 🚀" в повечето глави. Това е ново предизвикателство, което можете да завършите, използвайки GitHub Copilot и режим Agent. Ако не сте използвали режим Agent преди, той е способен не само да генерира текст, но и да създава и редактира файлове, да изпълнява команди и още.
Добавено е ново предизвикателство, търсете "GitHub Copilot Agent Challenge 🚀" в повечето глави. Това е ново предизвикателство за вас да го завършите, използвайки GitHub Copilot и режим Agent. Ако не сте използвали режима Agent досега, той еспособeн не само да генерира текст, но и да създава и редактира файлове, изпълнява команди и още.
### 📣 Съобщение - _Нов проект за създаване с Генеративен AI_
### 📣 Обявление - _Нов проект за изграждане сгенеративен AI_
Току-що добавен нов проект за AI асистент, разгледайте го [проект](./09-chat-project/README.md)
Току-що добавен нов проект AI Асистент, разгледайте го [тук](./9-chat-project/README.md)
### 📣 Съобщение - _Нова учебна програма_ за Генеративен AI за JavaScript беше току-що пусната
### 📣 Обявление - _Нова учебна програма_ за генеративен AI за JavaScript току-що беше пусната
Не пропускайте нашата нова учебна програма за Генеративен AI!
Не пропускайте нашата нова учебна програма за генеративен AI!
Посетете [https://aka.ms/genai-js-course](https://aka.ms/genai-js-course), за да започнете!
Всеки урок включва задача за изпълнение, проверка на знанията и предизвикателство, които ще ви помогнат да научите теми като:
- Създаване на запитвания и инженеринг на запитвания
- Генериране на текстови и визуални приложения
- Приложения за търсене
Всеки урок включва задача за изпълнение, проверка на знанията и предизвикателство, които ще ви упътят в изучаването на теми като:
- Подканяне и инженерство на подкани
- Генериране на приложения за текст и изображения
- Търсещи приложения
Посетете [https://aka.ms/genai-js-course](../../[https:/aka.ms/genai-js-course), за да започнете!
## 🌱 Започнете
## 🌱 Започване
> **Учители**, ние [включихме някои предложения](for-teachers.md) за това как да използвате тази учебна програма. Ще се радваме на вашата обратна връзка [в нашия форум за дискусии](https://github.com/microsoft/Web-Dev-For-Beginners/discussions/categories/teacher-corner)!
> **Учители**, ние сме [включили някои предложения](for-teachers.md) как да използвате тази учебна програма. Ще се радваме на вашата обратна връзка [в нашия форум за дискусии](https://github.com/microsoft/Web-Dev-For-Beginners/discussions/categories/teacher-corner)!
**[Ученици](https://aka.ms/student-page/?WT.mc_id=academic-77807-sagibbon)**, за всеки урок започнете спредварителен тест и продължете с четене на учебния материал, изпълнение на различните дейности и проверете разбирането си с тест след лекцията.
**[Учещи](https://aka.ms/student-page/?WT.mc_id=academic-77807-sagibbon)**, за всеки урок започнете свикторина преди лекцията и после преминете през учебния материал, завършвайки с различните активности и проверете разбирането си с викторина след лекцията.
За да подобрите учебния си опит, свържете сесвашите колеги, за да работите заедно по проектите! Дискусиите са насърчавани в нашия [форум за дискусии](https://github.com/microsoft/Web-Dev-For-Beginners/discussions), където нашият екип от модератори ще бъде на разположение да отговори на вашите въпроси.
За да подобрите учебния си опит, свържете сесколегите си за работа по проектите заедно! Насърчават се дискусии в нашия [форум за дискусии](https://github.com/microsoft/Web-Dev-For-Beginners/discussions), където нашият екип от модератори ще бъде на разположение да отговаря на вашите въпроси.
За да продължите образованието си, силно препоръчваме да разгледате [Microsoft Learn](https://learn.microsoft.com/users/wirelesslife/collections/p1ddcy5jwy0jkm?WT.mc_id=academic-77807-sagibbon) за допълнителни учебни материали.
За допълнително обучение силно препоръчваме да разгледате [Microsoft Learn](https://learn.microsoft.com/users/wirelesslife/collections/p1ddcy5jwy0jkm?WT.mc_id=academic-77807-sagibbon) за допълнителни учебни материали.
### 📋 Настройка на вашата среда
### 📋 Настройка на средата
Тази учебна програма има готова за използване среда за разработка! Когато започнете, можете да изберете да стартирате учебната програма в [Codespace](https://github.com/features/codespaces/) (_среда, базирана на браузър, без нужда от инсталации_), или локално на вашия компютър, използвайки текстов редактор като [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon).
Тази учебна програма разполага с готова за използване развойна среда! Когато започвате, можете да изберете да стартирате учебната програма в [Codespace](https://github.com/features/codespaces/) (_среда базирана на браузър, без нужда от инсталации_) или локално на компютъра си с помощта на текстов редактор като [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon).
#### Създайте вашето хранилище
За да запазите лесно работата си, препоръчваме да създадете свое собствено копие на това хранилище. Можете да направите това, като кликнете върху бутона **Use this template** в горната част на страницата. Това ще създаде ново хранилище във вашия GitHub акаунт с копие на учебната програма.
#### Създайте свое хранилище
За да запазвате лесно своята работа, препоръчително е да създадете свое копие на това хранилище. Можете да гонаправите, като кликнете бутона **Use this template** в горната част на страницата. Това ще създаде ново хранилище във вашия GitHub акаунт с копие на учебната програма.
Следвайте тези стъпки:
1. **Копирайте хранилището**: Кликнете върху бутона "Fork" в горния десен ъгъл на тази страница.
1. **Създайте форк на хранилището**: Кликнете бутона "Fork" в горния десен ъгъл на тази страница.
В копието на това хранилище, което сте създали, кликнете върху бутона **Code** и изберете **Open with Codespaces**. Това ще създаде нов Codespace, в който да работите.
За да стартирате тази учебна програма локално на вашия компютър, ще ви е необходим текстов редактор, браузър и инструмент за команден ред. Нашият първи урок, [Въведение в програмните езици и инструментите за работа](../../1-getting-started-lessons/1-intro-to-programming-languages), ще ви преведе през различни опции за всеки от тези инструменти, за да изберете това, което работи най-добре за вас.
#### Стартиране на учебната програма локално на компютъра
Нашата препоръка е да използвате [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon) като ваш редактор, който също има вграден [Терминал](https://code.visualstudio.com/docs/terminal/basics/?WT.mc_id=academic-77807-sagibbon). Можете да изтеглите Visual Studio Code [тук](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon).
За да стартирате тази учебна програма локално на компютъра си, ще ви е нужен текстов редактор, браузър и инструмент за команден ред. Първият ни урок, [Въведение в програмните езици и инструментите](../../1-getting-started-lessons/1-intro-to-programming-languages), ще ви преведе през различни опции за всеки от тези инструменти, за да изберете най-подходящото за вас.
Нашата препоръка е да използвате [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon) като редактор, който има и вграден [терминал](https://code.visualstudio.com/docs/terminal/basics/?WT.mc_id=academic-77807-sagibbon). Можете да свалите Visual Studio Code [тук](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon).
1. Клонирайте вашето хранилище на вашия компютър. Можете да направите това, като кликнете върху бутона **Code** и копирате URL адреса:
1. Клонирайте хранилището си на компютъра. Това става, като кликнете на бутона **Code** и копирате URL адреса:
[CodeSpace](./images/createcodespace.png)
След това отворете [Terminal](https://code.visualstudio.com/docs/terminal/basics/?WT.mc_id=academic-77807-sagibbon) в [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon) и изпълнете следната команда, като замените `<your-repository-url>`с URL адреса, който току-що сте копирали:
След това отворете [Terminal](https://code.visualstudio.com/docs/terminal/basics/?WT.mc_id=academic-77807-sagibbon) в [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-77807-sagibbon) и изпълнете следната команда, като замените `<your-repository-url>`с URL адреса, който току-що копирахте:
```bash
git clone <your-repository-url>
```
2. Отворете папката във Visual Studio Code. Можете да направите това, като кликнете върху **File** > **Open Folder** и изберете папката, която току-що сте клонирали.
2. Отворете папката във Visual Studio Code. Можете да направите това, като кликнете върху **File** > **Open Folder** и изберете папката, която току-що клонирахте.
> Препоръчителни разширения за Visual Studio Code:
> Препоръчани разширения за Visual Studio Code:
>
> * [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer&WT.mc_id=academic-77807-sagibbon) - за преглед на HTML страници във Visual Studio Code
> * [Copilot](https://marketplace.visualstudio.com/items?itemName=GitHub.copilot&WT.mc_id=academic-77807-sagibbon) - за по-бързо писане на код
## 📂 Всяка лекция включва:
## 📂 Всеки урок включва:
- по избор скица
- по избор допълнително видео
- предварителен тест за загрявка
- писмена лекция
- за проектно-базирани лекции, ръководства стъпка по стъпка за изграждане на проекта
- по избор скицник
- допълнително видео по избор
- предварителен топлинен квиз преди урока
- писмен урок
- за уроци, базирани на проекти, стъпка по стъпка ръководства как да се изгради проектът
- проверки на знанията
- предизвикателство
- допълнително четиво
- задача
- [тест след лекцията](https://ff-quizzes.netlify.app/web/)
> **Бележка относно тестовете**: Всички тестове се намират в папката Quiz-app, общо 48 тестас по три въпроса всеки. Теса достъпни [тук](https://ff-quizzes.netlify.app/web/), приложението за тестове може да се стартира локално или да се разположи в Azure; следвайте инструкциите в папката `quiz-app`.
## 🗃️ Лекции
| | Име на проекта | Преподавани концепции | Цели на обучението | Линк към лекцията | Автор |
| 01 | Първи стъпки | Въведение в програмирането и инструментите за работа | Научете основите на повечето програмни езици и за софтуера, който помага на професионалните разработчици да вършат работата си | [Въведение в програмните езици и инструментите за работа](./1-getting-started-lessons/1-intro-to-programming-languages/README.md) | Jasmine |
| 02 | Първи стъпки | Основи на GitHub, включително работа в екип | Как да използвате GitHub във вашия проект, как да си сътрудничите с другихора върху кодова база | [Въведение в GitHub](./1-getting-started-lessons/2-github-basics/README.md) | Floor |
| 03 | Първи стъпки | Достъпност | Научете основите на уеб достъпността | [Основи на достъпността](./1-getting-started-lessons/3-accessibility/README.md) | Christopher |
| 04 | Основи на JS |Типове данни в JavaScript | Основите на типовете данни в JavaScript | [Типове данни](./2-js-basics/1-data-types/README.md) | Jasmine |
| 05 | Основи на JS | Функции и методи | Научете за функциите и методите за управление на логическия поток на приложението | [Функции и методи](./2-js-basics/2-functions-methods/README.md) | Jasmine и Christopher |
| 06 | Основи на JS | Вземане на решения с JS | Научете как да създавате условия в кода си, използвайки методи за вземане на решения| [Вземане на решения](./2-js-basics/3-making-decisions/README.md) | Jasmine |
| 07 | Основи на JS | Масиви и цикли | Работа с данни, използвайки масиви и цикли в JavaScript | [Масиви и цикли](./2-js-basics/4-arrays-loops/README.md) | Jasmine |
| 08 | [Терариум](./3-terrarium/solution/README.md) | HTML на практика | Създайте HTML за онлайн терариум, като се фокусирате върху изграждането на оформление| [Въведение в HTML](./3-terrarium/1-intro-to-html/README.md) | Jen |
| 09 | [Терариум](./3-terrarium/solution/README.md) | CSS на практика | Създайте CSS за стилизиране на онлайн терариум, като се фокусирате върху основите на CSS, включително правенето на страницата адаптивна | [Въведение в CSS](./3-terrarium/2-intro-to-css/README.md) | Jen |
| 10 | [Терариум](./3-terrarium/solution/README.md) | Затваряния в JavaScript, манипулация на DOM | Създайте JavaScript, за да направите терариума функционален като интерфейс за влачене/пускане, фокусирайки се върху затваряния и манипулация на DOM | [Затваряния в JavaScript, манипулация на DOM](./3-terrarium/3-intro-to-DOM-and-closures/README.md) | Jen |
| 11 | [Игра за писане](./4-typing-game/solution/README.md) | Създаване на игра за писане | Научете как да използвате събития от клавиатурата, за да управлявате логиката на вашето JavaScript приложение | [Програмиране, базирано на събития](./4-typing-game/typing-game/README.md) | Christopher |
| 12 | [Еко браузър разширение](./5-browser-extension/solution/README.md) | Работа с браузъри | Научете как работят браузърите, тяхната история и как да създадете първите елементи на браузърно разширение | [За браузърите](./5-browser-extension/1-about-browsers/README.md) | Jen |
| 13 | [Еко браузър разширение](./5-browser-extension/solution/README.md) | Създаване на форма, извикване на API и съхраняване на променливи в локално хранилище | Създайте JavaScript елементи на вашето браузърно разширение, за да извикате API, използвайки променливи, съхранени в локално хранилище | [API, форми и локално хранилище](./5-browser-extension/2-forms-browsers-local-storage/README.md) | Jen |
| 14 | [Еко браузър разширение](./5-browser-extension/solution/README.md) | Фонови процеси в браузъра, уеб производителност | Използвайте фоновите процеси на браузъра, за да управлявате иконата на разширението; научете за уеб производителност и някои оптимизации | [Фонови задачи и производителност](./5-browser-extension/3-background-tasks-and-performance/README.md) | Jen |
| 15 | [Космическа игра](./6-space-game/solution/README.md) | По-напреднало разработване на игри с JavaScript | Научете за наследяване, използвайки както класове, така и композиция, и модела Pub/Sub, като подготовка за създаване на игра | [Въведение в напреднало разработване на игри](./6-space-game/1-introduction/README.md) | Chris |
| 16 | [Космическа игра](./6-space-game/solution/README.md) | Рисуване върху платно | Научете за API на Canvas, използван за рисуване на елементи върху екран | [Рисуване върху платно](./6-space-game/2-drawing-to-canvas/README.md) | Chris |
| 17 | [Космическа игра](./6-space-game/solution/README.md) | Движение на елементи по екрана | Открийте как елементите могат да се движат, използвайки декартови координати и API на Canvas | [Движение на елементи](./6-space-game/3-moving-elements-around/README.md) | Chris |
| 18 | [Космическа игра](./6-space-game/solution/README.md) | Засичане на сблъсъци | Направете елементите да се сблъскват и да реагират един на друг, използвайки натискания на клавиши, и осигурете функция за охлаждане за производителност на играта | [Засичане на сблъсъци](./6-space-game/4-collision-detection/README.md) | Chris |
| 19 | [Космическа игра](./6-space-game/solution/README.md) | Водене на резултат | Извършвайте математически изчисления, базирани на състоянието и производителността на играта | [Водене на резултат](./6-space-game/5-keeping-score/README.md) | Chris |
| 20 | [Космическа игра](./6-space-game/solution/README.md) | Завършване и рестартиране на играта | Научете за завършване и рестартиране на играта, включително почистване на ресурси и нулиране на стойностите на променливите | [Условие за завършване](./6-space-game/6-end-condition/README.md) | Chris |
| 21 | [Банкова апликация](./7-bank-project/solution/README.md) | HTML шаблони и маршрути в уебапликация | Научете как да създадете структурата на архитектурата на уебсайт с много страници, използвайки маршрути и HTML шаблони | [HTML шаблони и маршрути](./7-bank-project/1-template-route/README.md) | Yohan |
| 22 | [Банкова апликация](./7-bank-project/solution/README.md) | Създаване на форма за вход и регистрация | Научете за създаването на форми и обработката на рутинни проверки | [Форми](./7-bank-project/2-forms/README.md) | Yohan |
| 23 | [Банкова апликация](./7-bank-project/solution/README.md) | Методи за извличане и използване на данни | Как данните се движат в и извън вашата апликация, как да ги извличате, съхранявате и изтривате | [Данни](./7-bank-project/3-data/README.md) | Yohan |
| 24 | [Банкова апликация](./7-bank-project/solution/README.md) | Концепции за управление на състоянието | Научете как вашата апликация запазва състояние и как да го управлявате програмно | [Управление на състоянието](./7-bank-project/4-state-management/README.md) | Yohan |
| 25 | [Браузър/VSCode код](../../8-code-editor) | Работа с VSCode | Научете как да използвате редактор на код| [Използване на VSCode редактор на код](./8-code-editor/1-using-a-code-editor/README.md) | Chris |
| 26 | [AI Асистенти](./9-chat-project/README.md) | Работа с AI | Научете как да създадете свой собствен AI асистент | [Проект за AI асистент](./9-chat-project/README.md) | Chris |
- задание
- [квиз след урока](https://ff-quizzes.netlify.app/web/)
> **Бележка за квизовете**: Всички квизове са в папката Quiz-app, общо 48 квизас по три въпроса всеки. Теса достъпни [тук](https://ff-quizzes.netlify.app/web/), приложението за квизове може да се пуска локално или да се публикува в Azure; следвайте инструкциите в папката `quiz-app`.
## 🗃️ Уроци
| | Име на проекта | Преподавани концепции | Цели на обучението | Свързан урок | Автор |
| 01 | Първи стъпки | Въведение в програмирането и инструментите на занаята | Изучаване на основните принципи, които стоят зад повечето програмни езици и за софтуера, който помага на професионалните разработчици да вършат работата си | [Въведение в програмните езици и инструментите на занаята](./1-getting-started-lessons/1-intro-to-programming-languages/README.md) | Jasmine |
| 02 | Първи стъпки | Основи на GitHub, включително работа в екип| Как да използвате GitHub във вашия проект, как да си сътрудничите с други върху кодова база | [Въведение в GitHub](./1-getting-started-lessons/2-github-basics/README.md) | Floor |
| 03 | Първи стъпки | Достъпност| Научете основите на уеб достъпността | [Основи на достъпността](./1-getting-started-lessons/3-accessibility/README.md) | Christopher |
| 04 | JS Основи | Типове данни в JavaScript | Основите на типовете данни в JavaScript | [Типове данни](./2-js-basics/1-data-types/README.md) | Jasmine |
| 05 | JS Основи | Функции и методи| Научете за функциите и методите за управление на потока логика на приложение | [Функции и методи](./2-js-basics/2-functions-methods/README.md) | Jasmine и Christopher |
| 06 | JS Основи | Вземане на решения с JS | Научете как да създавате условия в кода си, използвайки методи за вземане на решения | [Вземане на решения](./2-js-basics/3-making-decisions/README.md) | Jasmine |
| 07 | JS Основи | Масиви и цикли | Работа с данни чрез масиви и цикли в JavaScript | [Масиви и цикли](./2-js-basics/4-arrays-loops/README.md) | Jasmine |
| 08 | [Terrarium](./3-terrarium/solution/README.md) | HTML на практика | Създайте HTML за онлайн терариум, съсредоточавайки се върху изграждането на оформление | [Въведение в HTML](./3-terrarium/1-intro-to-html/README.md) | Jen |
| 09 | [Terrarium](./3-terrarium/solution/README.md) | CSS на практика | Създайте CSS за стилизиране на онлайн терариума, като се фокусирате върху основите на CSS, включително направата на адаптивна страница | [Въведение в CSS](./3-terrarium/2-intro-to-css/README.md) | Jen |
| 10 | [Terrarium](./3-terrarium/solution/README.md) | JavaScript Closures, манипулиране на DOM | Създайте JavaScript, който да направи терариума функционален като интерфейс за плъзгане и пускане, съсредоточавайки се върху closing функции и манипулация на DOM | [JavaScript Closures, манипулация на DOM](./3-terrarium/3-intro-to-DOM-and-closures/README.md) | Jen |
| 11 | [Typing Game](./4-typing-game/solution/README.md) | Създаване на игра за писане | Научете как да използвате събития на клавиатурата за управление на логиката на вашето JavaScript приложение | [Събитийно-ориентирано програмиране](./4-typing-game/typing-game/README.md) | Christopher |
| 12 | [Green Browser Extension](./5-browser-extension/solution/README.md) | Работа с браузъри | Научете как работят браузърите, тяхната история и как да изградите първите елементи на разширение за браузър | [За браузърите](./5-browser-extension/1-about-browsers/README.md) | Jen |
| 13 | [Green Browser Extension](./5-browser-extension/solution/README.md) | Създаване на форма, извикване на API и съхраняване на променливи в локалното хранилище | Създайте JavaScript елементите на вашето браузърно разширение за извикване на API с използване на променливи, съхранявани в локалното хранилище | [APIs, формуляри и локално хранилище](./5-browser-extension/2-forms-browsers-local-storage/README.md) | Jen |
| 14 | [Green Browser Extension](./5-browser-extension/solution/README.md) | Фонови процеси в браузъра, уеб производителност| Използвайте фоновите процеси в браузъра, за да управлявате иконата на разширението; научете за уеб производителност и някои оптимизации | [Фонови задачи и производителност](./5-browser-extension/3-background-tasks-and-performance/README.md) | Jen |
| 15 | [Space Game](./6-space-game/solution/README.md) | По-напреднало разработване на игри с JavaScript | Научете за наследяването чрез класове и композиция и патърна Pub/Sub, като подготовка за създаване на игра| [Въведение в напреднала разработка на игри](./6-space-game/1-introduction/README.md) | Chris |
| 16 | [Space Game](./6-space-game/solution/README.md) | Рисуване върху канвас | Научете за API-то на Canvas, използвано за рисуване на елементи на екрана | [Рисуване върху Canvas](./6-space-game/2-drawing-to-canvas/README.md) | Chris |
| 17 | [Space Game](./6-space-game/solution/README.md) | Преместване на елементи на екрана | Разберете как елементите могат да придобият движение, използвайки картезиеви координати и Canvas API | [Преместване на елементи](./6-space-game/3-moving-elements-around/README.md) | Chris |
| 18 | [Space Game](./6-space-game/solution/README.md) | Откриване на сблъсъци | Направете елементите да се сблъскват и реагират един на друг с помощта на натискания на клавиши и осигурете cooldown функция за осигуряване на производителността на играта | [Откриване на сблъсъци](./6-space-game/4-collision-detection/README.md) | Chris |
| 19 | [Space Game](./6-space-game/solution/README.md) | Водене на резултат | Извършвайте математически изчисления въз основа на статуса и представянето на играта | [Водене на резултат](./6-space-game/5-keeping-score/README.md) | Chris |
| 20 | [Space Game](./6-space-game/solution/README.md) | Край и рестарт на играта | Научете как да приключите и рестартирате играта, включително изчистване на ресурси и нулиране на стойностите на променливи | [Условие за край](./6-space-game/6-end-condition/README.md) | Chris |
| 21 | [Banking App](./7-bank-project/solution/README.md) | HTML шаблони и маршрути в уебприложение | Научете как да създадете структурата на многостраничен уебсайт с използване на маршрутизация и HTML шаблони | [HTML шаблони и маршрути](./7-bank-project/1-template-route/README.md) | Yohan |
| 22 | [Banking App](./7-bank-project/solution/README.md) | Създаване на форма за влизане и регистрация | Научете как да създавате форми и да обработвате валидиращи процедури | [Форми](./7-bank-project/2-forms/README.md) | Yohan |
| 23 | [Banking App](./7-bank-project/solution/README.md) | Методи за извличане и използване на данни | Как данните влизат и излизат от вашето приложение, как да ги извличате, съхранявате и изтривате | [Данни](./7-bank-project/3-data/README.md) | Yohan |
| 24 | [Banking App](./7-bank-project/solution/README.md) | Концепции за управление на състоянието | Научете как вашето приложение задържа състояние и как да го управлявате програмно | [Управление на състоянието](./7-bank-project/4-state-management/README.md) | Yohan |
| 25 | [Browser/VScode Code](../../8-code-editor) | Работа с VScode | Научете как да използвате редактор на код | [Използване на VScode Code Editor](./8-code-editor/1-using-a-code-editor/README.md) | Chris |
| 26 | [AI Assistants](./9-chat-project/README.md) | Работа с AI | Научете как да изградите собствен AI асистент | [Проект AI асистент](./9-chat-project/README.md) | Chris |
## 🏫 Педагогика
Нашата учебна програма е създадена с две ключови педагогически принципи:
* обучение, базирано на проекти
* чести тестове
* чести квизове
Програмата преподава основите на JavaScript, HTML и CSS, както и най-новите инструменти и техники, използвани от съвременните уеб разработчици. Студентите ще имат възможност да придобият практически опит, като създадат игра за писане, виртуален терариум, екологично браузърно разширение, игра в стил "космически нашественици" и банкова апликация за бизнеси. До края на серията студентите ще са придобили солидно разбиране зауеб разработката.
Програмата учи основите на JavaScript, HTML и CSS, както и последните инструменти и техники, използвани от уеб разработчиците днес. Студентите ще имат възможност да придобият практически опит, като изграждат игра за писане, виртуален терариум, екологично разширение за браузър, игра в стил space-invaders и банково приложение за бизнеси. В края на поредицата студентите ще притежават солидно разбиране науеб разработката.
> 🎓 Можете да вземете първите няколко лекции от тази учебна програма като [Учебен път](https://docs.microsoft.com/learn/paths/web-development-101/?WT.mc_id=academic-77807-sagibbon) на Microsoft Learn!
> 🎓 Можете да преминете първите няколко урока от тази учебна програма като [Learn Path](https://docs.microsoft.com/learn/paths/web-development-101/?WT.mc_id=academic-77807-sagibbon) в Microsoft Learn!
Като гарантираме, че съдържанието е съобразено с проектите, процесът става по-ангажиращ за студентите и запазването на концепциите се увеличава. Освен това написахме няколко начални лекции за основите на JavaScript, за да въведем концепции, съчетани с видео от колекцията "[Серия за начинаещи: JavaScript](https://channel9.msdn.com/Series/Beginners-Series-to-JavaScript/?WT.mc_id=academic-77807-sagibbon)" от видео уроци, някои от чиито автори допринесоха за тази учебна програма.
Като осигуряваме съдържанието да е свързано с проекти, процесът става по-ангажиращ за студентите и задържането на концепциите се увеличава. Също така написахме няколко стартови урока по основите на JavaScript, за да въведем концепции, съчетани с видео от колекцията "[Набор за начинаещи към: JavaScript](https://channel9.msdn.com/Series/Beginners-Series-to-JavaScript/?WT.mc_id=academic-77807-sagibbon)", чиито някои автори допринесоха за тази учебна програма.
Освен това, тест с нисък риск преди клас задава намерението на студента към изучаване на дадена тема, докато втори тест след клас осигурява допълнително запазване на знанията. Тази учебна програма е проектирана да бъде гъвкава и забавна и може да бъде взета изцяло или частично. Проектите започват малки и стават все по-сложни до края на 12-седмичния цикъл.
Освен това, нискорисков квиз преди час задава нагласата на студента към изучаването на тема, докато втори квиз след часа осигурява допълнително задържане. Тази учебна програма е създадена да бъде гъвкава и забавна и може да се преминава изцяло или частично. Проектите започват малки и стават все по-сложни към края на 12-седмичния цикъл.
Докато умишлено избягвахме въвеждането на JavaScript рамки, за да се концентрираме върху основните умения, необходими като уеб разработчик преди приемането на рамка, добра следваща стъпка след завършване на тази учебна програма би било изучаването на Node.js чрез друга колекция от видеа: "[Серия за начинаещи: Node.js](https://channel9.msdn.com/Series/Beginners-Series-to-Nodejs/?WT.mc_id=academic-77807-sagibbon)".
Въпреки че целенасочено избягваме въвеждането на JavaScript рамки, за да се съсредоточим върху основните умения, необходими за уеб разработчик, преди да приемем рамка, добър следващ ход за завършване на тази учебна програма е изучаването на Node.js чрез друга колекция видеа: "[Набор за начинаещи към: Node.js](https://channel9.msdn.com/Series/Beginners-Series-to-Nodejs/?WT.mc_id=academic-77807-sagibbon)".
> Посетете нашите [Правила за поведение](CODE_OF_CONDUCT.md) и [Насоки за принос](CONTRIBUTING.md). Очакваме вашата конструктивна обратна връзка!
> Посетете нашия [Етичен кодекс](CODE_OF_CONDUCT.md) и насоките за [сътрудничество](CONTRIBUTING.md). Ние приветстваме вашата конструктивна обратна връзка!
## 🧭 Достъп офлайн
## 🧭 Офлайн достъп
Можете да използвате тази документация офлайн, като използвате [Docsify](https://docsify.js.org/#/). Клонирайте това хранилище, [инсталирайте Docsify](https://docsify.js.org/#/quickstart) на вашия локален компютър и след това в основната папка на това хранилище въведете `docsify serve`. Уебсайтът ще бъде достъпен на порт 3000 на вашия локален хост: `localhost:3000`.
Можете да използвате тази документация офлайн чрез [Docsify](https://docsify.js.org/#/). Форкнете това хранилище, [инсталирайте Docsify](https://docsify.js.org/#/quickstart) на локалния си компютър и след това в кореновата папка на това хранилище изпишете `docsify serve`. Уебсайтът ще бъде достъпен на порт 3000 на вашия локален хост: `localhost:3000`.
## 📘 PDF
PDF с всички лекции може да бъде намерен [тук](https://microsoft.github.io/Web-Dev-For-Beginners/pdf/readme.pdf).
PDF с всички уроци може да бъде намерен [тук](https://microsoft.github.io/Web-Dev-For-Beginners/pdf/readme.pdf).
## 🎒 Други курсове
Нашият екип произвежда и други курсове! Разгледайте:
Нашият екип създава и други курсове! Вижте:
### Azure / Edge / MCP / Agents
[](https://github.com/microsoft/AZD-for-beginners?WT.mc_id=academic-105485-koreyst)
[](https://github.com/microsoft/edgeai-for-beginners?WT.mc_id=academic-105485-koreyst)
[](https://github.com/microsoft/mcp-for-beginners?WT.mc_id=academic-105485-koreyst)
[](https://github.com/microsoft/ai-agents-for-beginners?WT.mc_id=academic-105485-koreyst)
<!-- CO-OP TRANSLATOR OTHER COURSES START -->
### LangChain
[](https://aka.ms/langchain4j-for-beginners)
[](https://aka.ms/langchainjs-for-beginners?WT.mc_id=m365-94501-dwahlin)
---
### Серия за Генеративен AI
[](https://github.com/microsoft/generative-ai-for-beginners?WT.mc_id=academic-105485-koreyst)
[-9333EA?style=for-the-badge&labelColor=E5E7EB&color=9333EA)](https://github.com/microsoft/Generative-AI-for-beginners-dotnet?WT.mc_id=academic-105485-koreyst)
[-C084FC?style=for-the-badge&labelColor=E5E7EB&color=C084FC)](https://github.com/microsoft/generative-ai-for-beginners-java?WT.mc_id=academic-105485-koreyst)
[-E879F9?style=for-the-badge&labelColor=E5E7EB&color=E879F9)](https://github.com/microsoft/generative-ai-with-javascript?WT.mc_id=academic-105485-koreyst)
### Azure / Edge / MCP / Агенти
[](https://github.com/microsoft/AZD-for-beginners?WT.mc_id=academic-105485-koreyst)
[](https://github.com/microsoft/edgeai-for-beginners?WT.mc_id=academic-105485-koreyst)
[](https://github.com/microsoft/mcp-for-beginners?WT.mc_id=academic-105485-koreyst)
[](https://github.com/microsoft/ai-agents-for-beginners?WT.mc_id=academic-105485-koreyst)
---
### Основно обучение
[](https://aka.ms/ml-beginners?WT.mc_id=academic-105485-koreyst)
[](https://aka.ms/datascience-beginners?WT.mc_id=academic-105485-koreyst)
[](https://aka.ms/ai-beginners?WT.mc_id=academic-105485-koreyst)
[](https://github.com/microsoft/Security-101?WT.mc_id=academic-96948-sayoung)
[](https://aka.ms/webdev-beginners?WT.mc_id=academic-105485-koreyst)
[](https://aka.ms/iot-beginners?WT.mc_id=academic-105485-koreyst)
[](https://github.com/microsoft/xr-development-for-beginners?WT.mc_id=academic-105485-koreyst)
### Серия за Генеративен AI
[](https://github.com/microsoft/generative-ai-for-beginners?WT.mc_id=academic-105485-koreyst)
[-9333EA?style=for-the-badge&labelColor=E5E7EB&color=9333EA)](https://github.com/microsoft/Generative-AI-for-beginners-dotnet?WT.mc_id=academic-105485-koreyst)
[-C084FC?style=for-the-badge&labelColor=E5E7EB&color=C084FC)](https://github.com/microsoft/generative-ai-for-beginners-java?WT.mc_id=academic-105485-koreyst)
[-E879F9?style=for-the-badge&labelColor=E5E7EB&color=E879F9)](https://github.com/microsoft/generative-ai-with-javascript?WT.mc_id=academic-105485-koreyst)
---
### Основно обучение
[](https://aka.ms/ml-beginners?WT.mc_id=academic-105485-koreyst)
[](https://aka.ms/datascience-beginners?WT.mc_id=academic-105485-koreyst)
[](https://aka.ms/ai-beginners?WT.mc_id=academic-105485-koreyst)
[](https://github.com/microsoft/Security-101?WT.mc_id=academic-96948-sayoung)
[](https://aka.ms/webdev-beginners?WT.mc_id=academic-105485-koreyst)
[](https://aka.ms/iot-beginners?WT.mc_id=academic-105485-koreyst)
[](https://github.com/microsoft/xr-development-for-beginners?WT.mc_id=academic-105485-koreyst)
### Серия Copilot
[](https://aka.ms/GitHubCopilotAI?WT.mc_id=academic-105485-koreyst)
[](https://github.com/microsoft/mastering-github-copilot-for-dotnet-csharp-developers?WT.mc_id=academic-105485-koreyst)
[](https://aka.ms/GitHubCopilotAI?WT.mc_id=academic-105485-koreyst)
[](https://github.com/microsoft/mastering-github-copilot-for-dotnet-csharp-developers?WT.mc_id=academic-105485-koreyst)
Ако се затруднявате или имате въпроси относно създаването на AI приложения, присъединете се:
Ако се затруднявате или имате въпроси относно създаването на AI приложения. Присъединете се към други ученици и опитни разработчици в дискусии за MCP. Това е подкрепяща общност, където въпросите са добре дошли и знанията се споделят свободно.
[](https://aka.ms/foundry/discord)
Ако имате обратна връзка за продукт или срещнете грешки при разработката, посетете:
Ако имате отзиви за продукта или срещнете грешки по време на разработка посетете:
[](https://aka.ms/foundry/forum)
Този репозиторий е лицензиран под MIT лиценз. Вижте файла [LICENSE](../../LICENSE) за повече информация.
Това хранилище е лицензирано под лиценза MIT. Вижте файла [LICENSE](../../LICENSE) за повече информация.
---
**Отказ от отговорност**:
Този документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за каквито и да било недоразумения или погрешни интерпретации, произтичащи от използването на този превод.
<!-- CO-OP TRANSLATOR DISCLAIMER START -->
**Отказ от отговорност**:
Този документ е преведен с помощта на AI преводаческа услуга [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи могат да съдържат грешки или неточности. Оригиналният документ на неговия език трябва да се счита за официален източник. За критична информация се препоръчва професионален човек преводач. Ние не носим отговорност за никакви недоразумения или погрешни тълкувания, произтичащи от използването на този превод.