Angular xizmatlar va DI
Xizmatlar qayta foydalanish mumkin bo‘lgan mantiqni tartibga soladi va tarkibiy qismlardan tashqari holat.
Xizmatlar va DI Essentials
- Nima: Xizmat qayta foydalanish mumkin bo‘lgan mantiq/holatga ega. DI (qaramlik kiritish) kerak bo‘lganda misollarni ta’minlaydi.
- Qo‘llanish doirasi: Umumiy singl uchun
rootda taqdim eting yoki alohida misollar uchun komponentni taqdim eting. - Foydalanish holatlari: ma’lumotlarni olish, keshlash, biznes qoidalari, o‘zaro componentlar holati.
- Aqliy model: DI quvvat manbaiga o‘xshaydi: siz ulang va Angular sizga tayyor namunani beradi.
- Dekorator: Boshqa xizmatlarni kiritadigan classlarda
@Injectable()dan foydalaning.
import { Injectable } from '@angular/core';
@Injectable({ providedIn: 'root' })
export class CounterService { value = 0; inc() { this.value++; } }
// Inject in a component
// constructor(public counter: CounterService) {}
Eslatmalar:
- Tegishli: Xizmatlarni iste’mol qilish uchun componentlar, xizmatlardan foydalanadigan qo‘riqchilar uchun Router va ma’lumotlarni oladigan xizmatlar uchun HTTP-ga qarang.
- Ilova miqyosidagi singletonlar uchun
@Injectable({ providedIn: 'root' })dan foydalaning. - Izolyatsiya qilingan misollar kerak bo‘lganda komponentni taqdim eting.
- Konstruktorlardan tashqari bog‘liqliklarni olish uchun marshrut qo‘riqchilari kabi funksiyalarda
inject()dan foydalaning.
Xizmat asoslari
- Darslarni
@Injectable()bilan bezang (agar ular boshqa xizmatlarni kiritsa, talab qilinadi). - Komponentlarda foydalanish uchun xizmatlarni konstruktorlarga kiriting.
- Umumiy singleton uchun
providedIn: 'root'’dan foydalaning.
@Injectable({ providedIn: 'root' })
export class DataService {}
// class App { constructor(private data: DataService) {} }
Misol
import { bootstrapApplication } from '@angular/platform-browser';
import { Component, Injectable } from '@angular/core';
@Injectable({ providedIn: 'root' })
export class CounterService {
value = 0;
inc() { this.value++; }
dec() { this.value--; }
reset() { this.value = 0; }
}
@Component({
selector: 'app-root',
standalone: true,
template: `
<h3>Services</h3>
<p>Counter: {{ counter.value }}</p>
<button (click)="counter.inc()">+</button>
<button (click)="counter.dec()">-</button>
<button (click)="counter.reset()">Reset</button>
`
})
export class App {
constructor(public counter: CounterService) {}
}
bootstrapApplication(App);
<app-root></app-root>
Misol tushuntirildi
@Injectable({ providedIn: 'root' }): Ilova bo‘ylab mavjud bo‘lgan singleton xizmatini ro‘yxatdan o‘tkazadi.- Inject in konstruktor:
constructor(public counter: CounterService)xizmatni shablonga ochib beradi. - Metodlar: Umumiy holatni yangilash uchun
inc()/dec()/reset()metodlarini chaqiring.
Eslatmalar:
- In’ektsiya paytida metama’lumotlar talab qilinadi: Agar xizmat boshqa xizmatlarni kiritsa, DI metadata yaratishi uchun
@Injectable()ni qo‘shing. - Minimal holatni saqlang: xizmatlarda katta umumiy o‘zgaruvchan holatdan saqlaning; Aniq usullardan foydalaning va qiymatlarni qaytaring.
- Mustaqil yuklash: Provayderlar kerak bo‘lganda ro‘yxatdan o‘tganligiga ishonch hosil qiling va funktsional konstruktsiyalarda (masalan, qo‘riqchilar)
inject()dan foydalaning.
componentlar bo‘yicha umumiy xizmat
providedIn: 'root'butun ilova bo‘ylab bitta nusxani ulashadi.- Bitta komponentda yangilanish boshqalarda xuddi shu xizmatdan foydalanishni aks ettiradi.
<counter-a></counter-a>
<counter-b></counter-b>
<!-- Both use the same service instance -->
Misol
import { bootstrapApplication } from '@angular/platform-browser';
import { Component, Injectable } from '@angular/core';
@Injectable({ providedIn: 'root' })
export class CounterService {
value = 0;
inc() { this.value++; }
dec() { this.value--; }
}
@Component({
selector: 'counter-a',
standalone: true,
template: `
<h4>Counter A</h4>
<p>Value: {{ counter.value }}</p>
<button (click)="counter.inc()">+1</button>
<button (click)="counter.dec()">-1</button>
`
})
export class CounterA {
constructor(public counter: CounterService) {}
}
@Component({
selector: 'counter-b',
standalone: true,
template: `
<h4>Counter B</h4>
<p>Value: {{ counter.value }}</p>
<button (click)="counter.inc()">+1</button>
<button (click)="counter.dec()">-1</button>
`
})
export class CounterB {
constructor(public counter: CounterService) {}
}
@Component({
selector: 'app-root',
standalone: true,
imports: [CounterA, CounterB],
template: `
<h3>Shared Service Across Components</h3>
<counter-a></counter-a>
<counter-b></counter-b>
<p><em>Both components use the same CounterService instance.</em></p>
`
})
export class App {}
bootstrapApplication(App);
<app-root></app-root>
Misol tushuntirildi
providedIn: 'root'butun ilova bo‘ylab bitta nusxani ulashadi.- Umumiy holat: Bir komponentda +/− tugmasini bosish ikkinchisida ko‘rsatilgan qiymatni yangilaydi.
- Shablonga kirish: Shablon
counter.valueni o‘qiy olishi va metodlarni chaqira olishi uchunpublicsifatida kiritilgan.
Eslatmalar:
- Singleton va mahalliy:
providedIn: 'root'bitta umumiy misolni beradi; komponentda taqdim etish har bir kichik daraxt uchun alohida misollarni yaratadi. - Qamrash haqida o‘ylang: kutilmagan hodisalarga yo‘l qo‘ymaslik uchun ulashish ehtiyojlaringizga mos keladigan darajada taqdim eting.
Komponent taqdim etgan servis (ierarxik DI)
- Komponentning
providers-da uning pastki daraxti uchun mahalliy misol yaratish uchun xizmatni taqdim eting. - Qardosh pastki daraxtlar alohida misollarni oladi.
@Component({ providers: [LocalCounterService] })
export class Panel {}
Misol
import { bootstrapApplication } from '@angular/platform-browser';
import { Component, Injectable } from '@angular/core';
import { CommonModule } from '@angular/common';
@Injectable()
export class LocalCounterService {
id = Math.floor(Math.random() * 10000);
value = 0;
inc() { this.value++; }
}
@Component({
selector: 'counter-view',
standalone: true,
template: `
<p>Service #{{ svc.id }} value: {{ svc.value }}</p>
<button (click)="svc.inc()">+1</button>
`
})
export class CounterView {
constructor(public svc: LocalCounterService) {}
}
@Component({
selector: 'panel-a',
standalone: true,
imports: [CommonModule, CounterView],
providers: [LocalCounterService],
template: `
<h4>Panel A (own provider)</h4>
<counter-view></counter-view>
<counter-view></counter-view>
`
})
export class PanelA {}
@Component({
selector: 'panel-b',
standalone: true,
imports: [CommonModule, CounterView],
providers: [LocalCounterService],
template: `
<h4>Panel B (own provider)</h4>
<counter-view></counter-view>
<counter-view></counter-view>
`
})
export class PanelB {}
@Component({
selector: 'app-root',
standalone: true,
imports: [CommonModule, PanelA, PanelB],
styles: [`
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 16px; }
h4 { margin: 0 0 8px; }
button { margin-top: 6px; }
`],
template: `
<h3>Component-Provided Service (Hierarchical DI)</h3>
<p>Each panel provides its own service instance.</p>
<p>Counters inside the same panel share the instance.</p>
<p>Different panels do not.</p>
<div class="grid">
<panel-a></panel-a>
<panel-b></panel-b>
</div>
`
})
export class App {}
bootstrapApplication(App);
<app-root></app-root>
Misol tushuntirildi
providers: [LocalCounterService]: Har bir panel komponenti o‘zining pastki daraxti uchun o‘z xizmat namunasini oladi.- Panel ichida: Bir nechta
CounterViewbolalari bir xil mahalliy misolni baham ko‘radi. - Panellar o‘rtasida: Panel A va Panel B turli misollarga ega (turli id qiymatlarini ko‘ring).
Eslatmalar:
- Kutilayotgan bir nechta misollar: Har bir taqdim etilgan component quyi daraxti o‘z namunasini oladi; birodarlar buni baham ko‘rmaydilar.
- Doiraviy bog‘liqlikdan saqlaning: bir-birini in’ektsiya qiladigan ikkita xizmat muvaffaqiyatsiz bo‘ladi; uchinchi xizmatga umumiy mantiqni ajratib oling yoki qayta loyihalash.
Xizmatni loyihalash bo‘yicha maslahatlar
Xizmatlarni diqqat markazida tuting va oson sinovdan o‘tkazing:
- Komponentlarni ulashdan saqlaning: komponentlarni xizmatlarga kiritmang; xizmatlarni UI-agnostik holda saqlang.
- Aniq API’larni ko‘rsatish: Oddiy qiymatlarni yoki Kuzatiladiganlarni qaytaruvchi kichik usullardan foydalaning; ichki holatni maxfiy saqlang.
- Tokenlar orqali konfiguratsiya: Sinov va qayta foydalanishni soddalashtirish uchun sozlanishi qiymatlar uchun inyeksion tokenlardan (noyob qidirish kaliti, odatda class yoki
InjectionTokenobyekti) foydalaning. - Qasddan qamrov: Ilova miqyosidagi singletonlar uchun
providedIn: 'root'dan foydalaning; alohida holatlar uchun komponentni taqdim eting.
W3Schools Pathfinder
Yutuqlaringizni kuzating – bu bepul!
