تزریق وابستگی
تزریق وابستگی (Dependency Injection) در انگولار یک الگوی طراحی قدرتمند است که امکان میدهد کامپوننتها و سرویسها بدون نیاز به ایجاد مستقیم وابستگیهایشان، به منابع مورد نیاز دسترسی پیدا کنند. این الگو برای مدیریت وضعیت (state management)، جریان داده (data flow) و چرخه حیات (lifecycle) کامپوننتها در برنامههای مدرن وب و SPAها حیاتی است. استفاده صحیح از تزریق وابستگی باعث افزایش تستپذیری، کاهش Prop Drilling و جلوگیری از رندرهای غیرضروری میشود و ساختار برنامه را ماژولار و مقیاسپذیر میسازد.
در توسعه انگولار، هرگاه یک کامپوننت نیاز به سرویس یا منبع دادهای دارد، تزریق وابستگی به کار میآید. این کار معمولاً از طریق سازنده (constructor) انجام میشود و انگولار به صورت خودکار نمونه مناسب از سرویس را ارائه میدهد. با این روش، کامپوننت تنها بر روی رابط کاربری و مدیریت تعامل کاربر متمرکز میشود، در حالی که سرویسها وظیفه مدیریت داده و منطق کسبوکار را بر عهده دارند.
در این آموزش، خواننده یاد میگیرد که چگونه از تزریق وابستگی برای ساخت کامپوننتهای قابل استفاده مجدد، مدیریت جریان داده و بهینهسازی عملکرد استفاده کند. مثالها شامل Lifecycle Hooks، Observables، مدیریت خطا و جریانهای داده غیرهمزمان هستند. پس از مطالعه این محتوا، توسعهدهندگان قادر خواهند بود برنامههای انگولار مقاوم، بهینه و قابل نگهداری بسازند.
مثال پایه
typescriptimport { Injectable, Component } from '@angular/core';
// سرویس برای مدیریت وضعیت
@Injectable({
providedIn: 'root'
})
export class DataService {
private message: string = 'سلام از DataService!';
getMessage(): string {
return this.message;
}
setMessage(newMessage: string): void {
this.message = newMessage;
}
}
// کامپوننت که از سرویس استفاده میکند
@Component({
selector: 'app-message',
template: ` <div> <h2>{{ message }}</h2> <input [(ngModel)]="newMessage" placeholder="پیام جدید را وارد کنید" /> <button (click)="updateMessage()">بهروزرسانی پیام</button> </div>
`
})
export class MessageComponent {
message: string = '';
newMessage: string = '';
constructor(private dataService: DataService) {
this.message = this.dataService.getMessage();
}
updateMessage(): void {
this.dataService.setMessage(this.newMessage);
this.message = this.dataService.getMessage();
}
}
در این مثال، DataService مسئول نگهداری یک پیام ساده است. با استفاده از @Injectable({ providedIn: 'root' })، انگولار یک نمونه Singleton از سرویس را در کل برنامه فراهم میکند، بنابراین مدیریت وضعیت بین کامپوننتها ساده است و ایجاد نمونههای تکراری جلوگیری میشود.
کامپوننت MessageComponent سرویس را از طریق سازنده خود دریافت میکند، بنابراین انگولار به صورت خودکار نمونه سرویس را تزریق میکند. این ساختار از ایجاد مستقیم سرویس در کامپوننت جلوگیری میکند و باعث جداسازی منطق و رابط کاربری میشود. استفاده از [(ngModel)] و event binding نشان میدهد که چگونه سرویس میتواند وضعیت را بهروزرسانی کرده و تغییرات در UI منعکس شود.
تزریق وابستگی همچنین امکان تست واحد (unit testing) مستقل کامپوننتها با استفاده از mock سرویسها را فراهم میکند. مدیریت چرخه حیات و منابع توسط انگولار باعث رفتار پایدار و استفاده بهینه از منابع میشود که در پروژههای بزرگ SPA اهمیت دارد.
مثال کاربردی
typescriptimport { Injectable, Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
// سرویس برای دریافت دادههای API
@Injectable({
providedIn: 'root'
})
export class ApiService {
private apiUrl = '[https://jsonplaceholder.typicode.com/posts](https://jsonplaceholder.typicode.com/posts)';
constructor(private http: HttpClient) {}
fetchPosts(): Observable<any> {
return this.http.get(this.apiUrl);
}
}
// کامپوننتی که از ApiService استفاده میکند
@Component({
selector: 'app-posts',
template: ` <div *ngIf="posts.length; else loading"> <h3>لیست پستها:</h3> <ul> <li *ngFor="let post of posts">{{ post.title }}</li> </ul> </div> <ng-template #loading> <p>در حال بارگذاری دادهها...</p> </ng-template>
`
})
export class PostsComponent implements OnInit {
posts: any[] = [];
constructor(private apiService: ApiService) {}
ngOnInit(): void {
this.apiService.fetchPosts().subscribe({
next: (data) => (this.posts = data),
error: (err) => console.error('خطا در دریافت دادهها', err)
});
}
}
در این مثال پیشرفته، DI با پردازش دادههای غیرهمزمان ترکیب شده است. ApiService با استفاده از HttpClient دادهها را از API دریافت میکند و یک Observable بازمیگرداند. PostsComponent سرویس را تزریق کرده و در ngOnInit به Observable subscribe میکند. استفاده از ngFor و ngIf/ng-template برای نمایش لیست دادهها و وضعیت بارگذاری انجام شده است.
DI تضمین میکند که کامپوننت مستقل از منبع داده باقی بماند. بهترین شیوهها مانند encapsulate کردن منطق در سرویس، استفاده از Observables، مدیریت خطا و استفاده صحیح از Lifecycle Hooks نشان داده شده است. این الگو Prop Drilling را کاهش میدهد، ثبات state را تضمین میکند و عملکرد rendering را بهینه میکند.
بهترین شیوههای انگولار برای تزریق وابستگی شامل encapsulate کردن منطق در سرویس، تمرکز کامپوننتها بر UI و تعاملات، استفاده از providedIn برای کنترل محدوده سرویس، تزریق از طریق سازنده و استفاده از ChangeDetectionStrategy.OnPush است. خطاهای رایج شامل mutate مستقیم state در کامپوننت، Prop Drilling بیش از حد، نادیده گرفتن Lifecycle Hooks و ایجاد نمونههای تکراری است.
برای دیباگ از Angular DevTools استفاده کنید. بهینهسازی عملکرد شامل کاهش نمونههای سرویس غیرضروری، unsubscribe از Observables و استفاده از Lazy Loading و OnPush است. از نظر امنیتی، دادههای سرویس را validate کرده و از حملات XSS و CSRF محافظت کنید.
📊 جدول مرجع
انگولار Element/Concept | Description | Usage Example |
---|---|---|
@Injectable | سرویس را قابل تزریق میکند | @Injectable({ providedIn: 'root' }) |
Constructor Injection | تزریق وابستگیها از طریق سازنده | constructor(private dataService: DataService) {} |
ngOnInit | Lifecycle hook برای مقداردهی اولیه | ngOnInit(): void { this.loadData(); } |
HttpClient | ارسال درخواست HTTP | this.http.get('url').subscribe(data => ...) |
Observable | مدیریت جریان دادههای غیرهمزمان | this.apiService.fetchPosts().subscribe(posts => this.posts = posts) |
ChangeDetectionStrategy.OnPush | بهینهسازی عملکرد رندر | @Component({ changeDetection: ChangeDetectionStrategy.OnPush }) |
درک تزریق وابستگی به توسعهدهندگان امکان میدهد کامپوننتهای ماژولار، maintainable و تستپذیر بسازند. DI کامپوننتها را از سرویسها جدا کرده، مدیریت state را ساده کرده و جریان دادهی ثابت را تضمین میکند. این دانش برای SPAها و برنامههای enterprise بزرگ ضروری است.
گامهای بعدی شامل یادگیری مدیریت state پیشرفته با NgRx، پیادهسازی Lazy-Loaded modules، استفاده از OnPush change detection و طراحی معماری مقیاسپذیر در انگولار است. در عمل، چندین کامپوننت قابل استفاده مجدد را با سرویسهای مشترک از طریق DI مرتبط کرده و با unit tests آنها را بررسی کنید. منابع مفید شامل مستندات رسمی Angular، نمونههای GitHub و Angular DevTools هستند.
🧠 دانش خود را بیازمایید
دانش خود را بیازمایید
خود را با این آزمون تعاملی به چالش بکشید و ببینید موضوع را چقدر خوب درک کردهاید
📝 دستورالعملها
- هر سوال را با دقت بخوانید
- بهترین پاسخ را برای هر سوال انتخاب کنید
- میتوانید آزمون را هر چند بار که میخواهید تکرار کنید
- پیشرفت شما در بالا نمایش داده میشود