در این مقاله قصد داریم نگاهی به فریمورک Angular داشته باشیم . بیایید وارد آن شویم!

معرفی

امروزه، ما گزینه های زیادی برای توسعه چیزی داریم که برای پلتفرم های مختلف آماده است. با این حال، Angular راه خود را باز کرده است و اکنون یکی از مهم ترین بازیگران است. بیایید ببینیم چیست و چگونه کار می کند.

ما می‌توانیم مستقیماً وارد کد یک پروژه شویم، اما احتمالاً چند چیز را از دست می‌دهیم. بنابراین، در اینجا، ما قصد داریم به معماری Angular نگاهی بیندازیم تا مفاهیم و عناصر مختلفی را که این آخرین مورد استفاده قرار می‌دهد را درک کنیم.

Angular چیست؟

اکنون، وقتی از Angular صحبت می کنیم ، در مورد Angular 2 یا Angular 5 صحبت می کنیم . Angular بازنویسی کامل چارچوب AngularJS است . Angular به عنوان رویکردی متفاوت از مدل قبلی خود.

Angular به ما اجازه می دهد تا برنامه های کاربردی را در تمام پلتفرم ها بسازیم. این یک پلت فرم منبع باز است که از TypeScript استفاده می کند . در چند کلمه، TypeScript یک ابر مجموعه نحوی دقیق جاوا اسکریپت است و تایپ استاتیک اختیاری را به زبان اضافه می کند.

نمای کلی معماری

Angular در TypeScript نوشته شده است و عملکردهای اصلی و اختیاری را به عنوان مجموعه ای از کتابخانه های TypeScript که می توانیم وارد کنیم پیاده سازی می کند.

یک برنامه Angular ، برای بلوک های ساختمانی، چیزی به نام NgModules دارد . یک برنامه Angular توسط مجموعه ای از NgModules تعریف می شود . یک برنامه همیشه حداقل یک ماژول ریشه دارد که بوت استرپ را فعال می کند. یک NgModule از اجزای سازنده ساخته شده است . هر برنامه حداقل یک مؤلفه ریشه دارد .

کامپوننت ها و چیزهایی مانند خدمات فقط کلاس هستند. با این حال، آنها با تزئیناتی مشخص شده اند که به Angular می گوید چگونه از آنها استفاده کند.

Angular یک سرویس روتر ارائه می دهد که به ما کمک می کند تا مسیرهای ناوبری را در بین View های مختلف تعریف کنیم .

ماژول ها

برنامه های زاویه ای ماژولار هستند و این سیستم ماژولار NgModules نامیده می شود .

یک NgModule مجموعه ای از کامپوننت ها را تعریف می کند . یک کد مرتبط با NgModule برای تشکیل واحدهای عملکردی. هر برنامه Angular دارای یک Root Module است که به طور معمول AppModule نام دارد که مکانیزم بوت استرپ را برای راه اندازی برنامه ارائه می دهد.

حتی اگر متفاوت و نامرتبط باشند، NgModules ، مانند ماژول‌های جاوا اسکریپت ، می‌توانند عملکرد را از سایر NgModules وارد کنند و اجازه دهند عملکرد خود را صادر کرده و توسط NgModules دیگر استفاده کنند . آنچه ما کتابخانه های انگولار می نامیم NgModules هستند .

ما یک NgModule را با تزئین کلاس خود با دکوراتور ” @NgModule ” اعلام می کنیم. این دکوراتور یک شی فوق داده است که ویژگی های آن ماژول را توصیف می کند. مهمترین خصوصیات که آرایه هستند به شرح زیر است:

  • اعلامیه ها – اجزا ، دستورالعمل ها و لوله هایی که به NgModule تعلق دارند
  • صادرات – زیرمجموعه ای از اعلان ها که باید در اجزای سایر NgModules قابل مشاهده و قابل استفاده باشد.
  • imports – ماژول‌های دیگری که کلاس‌های صادراتی آنها توسط مؤلفه‌های اعلام‌شده در NgModule مورد نیاز است
  • ارائه دهندگان — لیستی از خدمات مورد نیاز که، به دلیل اینکه در اینجا فهرست شده اند، در سراسر برنامه در دسترس هستند
  • بوت استرپ – نمای برنامه اصلی ، به نام Root Component ، که میزبان سایر نماهای برنامه است. (فقط ماژول ریشه باید این ویژگی بوت استرپ را تنظیم کند)

یک NgModule یک زمینه تلفیقی برای اجزای مختلف خود فراهم می کند . بنابراین، اجزایی که به یک NgModule تعلق دارند ، یک زمینه کامپایل را به اشتراک می گذارند. NgModules یک بلوک منسجم از عملکرد را تعریف می کند.

ماژول ریشه برنامه ما همانی است که برای راه اندازی برنامه بوت استرپ می کنیم. برنامه با بوت استرپ ریشه AppModule راه اندازی می شود . ما همچنین آن را ورودی Component می نامیم . فرآیند راه‌اندازی اجزای فهرست شده در آرایه « bootstrap » را ایجاد می‌کند و هر کدام را در DOM مرورگر وارد می‌کند . بنابراین، هر مؤلفه راه‌اندازی شده ، پایه درخت مؤلفه‌های خودش است .

همانطور که دیدیم، می‌توانیم یک ماژول ریشه داشته باشیم ، اما می‌توانیم چیزی را که ماژول‌های ویژگی می‌نامیم داشته باشیم . یک ماژول ویژگی مجموعه ای منسجم از عملکرد را ارائه می دهد که بر نیازهای یک برنامه خاص متمرکز شده است. ما می‌توانیم همه کارها را در ماژول ریشه انجام دهیم ، اما یک ماژول ویژگی به ما کمک می‌کند برنامه‌مان را به مناطق متمرکز تقسیم کنیم. با این حال، ساختار یک ماژول ویژگی دقیقاً مشابه ساختار یک ماژول ریشه است .

در زیر، می‌توانیم نمونه‌ای از اینکه چگونه یک NgModule به نظر می‌رسد را بیابیم . در اینجا، آن AppModule است :

اجزاء

یک مؤلفه یک وصله از صفحه نمایش به نام View را کنترل می کند . منطق یک Component در داخل یک کلاس تعریف می شود. Angular هنگام حرکت کاربر در برنامه، کامپوننت ها را ایجاد، به روز رسانی و از بین می برد .

یک کامپوننت توسط دکوراتور « @Component » شناسایی می‌شود که مجموعه‌ای از ویژگی‌ها را دارد. بیشترین خواص وارداتی موارد زیر است:

  • انتخابگر – نحوه ارجاع مؤلفه در HTML را نشان می دهد . به عبارت ساده، با تگ HTML مطابقت دارد .
  • templateUrl – مسیر قالب HTML را می دهد .
  • ارائه دهندگان – آرایه ای از ارائه دهندگان تزریق وابستگی برای خدماتی که مؤلفه به آن نیاز دارد.

توجه داشته باشید که به جای ویژگی templateUrl ، می‌توانیم از ویژگی template استفاده کنیم که به ما امکان می‌دهد قالب HTML را به صورت درون خطی ارائه کنیم.

یک کامپوننت یک View دارد و این مورد آخر از طریق یک قالب HTML تعریف می شود . این فایل HTML همچنین حاوی برخی از عناصر نحوی است که در Angular گنجانده شده است .

یک کامپوننت معمولاً به شکل زیر خواهد بود:

قبل از ادامه بیشتر با Components ، اجازه دهید نگاهی به چند عنصر دیگر بیاندازیم تا برخی از اصطلاحات را ساده کنیم که بعداً استفاده خواهیم کرد.

خدمات

یک سرویس برای تعریف چیزهایی که نمی توانند در یک مؤلفه قرار بگیرند و دلیل وجود آنها را در تفکیک نگرانی ها پیدا می کند مفید است . یک سرویس یک کلاس با هدف مشخص است. به عنوان مثال، زمانی که دو یا چند کامپوننت یا چیزهای دیگر نیاز به دسترسی به داده های مشابه دارند ، یا اگر می خواهیم تعاملات با یک وب سرور را محصور کنیم یا می خواهیم تعریف کنیم که چگونه ورودی های کاربر را اعتبار سنجی کنیم، باید یک سرویس ایجاد کنیم.

سرویس ها Singletons هستند ، بنابراین تنها یک نمونه از هر سرویسی که تعریف می کنیم وجود دارد . آنها اشیایی بدون حالت هستند که می توانند از هر مؤلفه ای فراخوانی شوند . هدف آنها این است که به ما کمک کنند تا برنامه خود را به واحدهای منطقی کوچک و متفاوتی که قابل استفاده مجدد هستند تقسیم کنیم.

یک سرویس یک کلاس ساده است و می تواند به شکل زیر باشد:

تزریق وابستگی

تزریق وابستگی موضوع بزرگی است. Dependency Injection که DI نیز نامیده می شود ، یک الگوی طراحی است که در آن یک یا چند وابستگی ( سرویس ) به یک شی وابسته ( Client ) تزریق می شود. این الگو به ما اجازه می‌دهد تا با جدا کردن ایجاد وابستگی‌های مشتری از رفتار خود، یک معماری با جفت آزاد را پیاده‌سازی کنیم.

ما می‌توانیم این الگو را زمانی اعمال کنیم که می‌خواهیم دانش پیاده‌سازی بتن را از اشیا حذف کنیم، اما همچنین زمانی که می‌خواهیم کد قابل آزمایش بهتری را به‌صورت مجزا و با استفاده از اشیاء ساختگی دریافت کنیم.

الگوی DI معمولاً برای پیاده‌سازی اصل وارونگی کنترل استفاده می‌شود که در چند کلمه، قسمت آنچه را که باید انجام داد از قسمت زمانی که باید انجام شود جدا می‌کند . به عبارت دیگر، اجازه دادن به دیگری برای کنترل جریان کنترل است. این بر اساس اصل هالیوود است : ” با ما تماس نگیرید، ما با شما تماس خواهیم گرفت “.

تزریق وابستگی را می توان با استفاده از ” سازنده ” یک کلاس یا متدهای ” setter ” به دست آورد. همچنین می توان با یک ظرف که نمونه سازی اشیاء دیگر را کنترل می کند، به دست آورد.

در Angular ، DI به طور گسترده مورد استفاده قرار می گیرد و می توانیم لحظه ای به آن بپردازیم.

Angular از چارچوب تزریق وابستگی خود استفاده می کند که اساساً از سه چیز استفاده می کند:

  • Injector که API ها را در معرض دید قرار می دهد . مسئول ایجاد نمونه های Service و تزریق آنها به کلاس ها است.
  • ارائه‌دهنده ، که به انژکتور می‌گوید چگونه یک نمونه از وابستگی ایجاد کند.
  • Dependency ، نوع آن که یک شی باید ایجاد شود .

Angular دارای سیستم تزریق وابستگی سلسله مراتبی است . درختی از Injectors وجود دارد که به موازات درخت Component یک برنامه کاربردی است . یک برنامه ممکن است چندین انژکتور داشته باشد . این بدان معناست که ما می توانیم ارائه دهندگان را در سطوح مختلف پیکربندی کنیم:

  • برای کل برنامه هنگام بوت استرپ کردن آن. همه انژکتورهای فرعی ارائه دهنده را می بینند و نمونه مرتبط با آن را به اشتراک می گذارند. همیشه همین نمونه خواهد بود.
  • برای یک جزء خاص و اجزای فرعی آن . سایر مؤلفه‌ها ارائه‌دهنده را نمی‌بینند .
  • برای خدمات . آنها از یکی از Injectors از عنصری استفاده می کنند که زنجیره سرویس را فراخوانی می کند .

هنگام استفاده از DI با Angular ، ما عمدتاً دکوراتور ” @Injectable ” را خواهیم دید. این دکوراتور یک کلاس را به عنوان در دسترس Injector برای ایجاد علامت گذاری می کند.

در یک برنامه Angular ، Components از خدمات استفاده می کند . یک مؤلفه نباید سرویس ایجاد کند . بنابراین، ما خدمات مختلف مورد نیاز را به اجزای مختلف تزریق می کنیم . هنگامی که Angular یک نمونه جدید از کلاس Component ایجاد می کند، با مشاهده انواع پارامترهای سازنده آن ، مشخص می کند که به کدام سرویس ها یا وابستگی های دیگری نیاز دارد . هنگامی که Angular متوجه می شود که یک مؤلفه به یک سرویس نیاز دارد ، بررسی می کند که آیا Injector قبلاً نمونه های موجود از همان سرویس را دارد یا خیر . اگر نمونه‌ای از آن سرویس درخواستی وجود نداشته باشد، Injector با استفاده از ارائه‌دهنده ثبت‌شده، آن را ایجاد می‌کند و قبل از برگرداندن سرویس به Angular، آن را به Injector اضافه می‌کند .

ارائه دهنده دستوری برای ایجاد وابستگی است. ما باید حداقل یک ارائه دهنده از هر سرویسی را که می خواهیم استفاده کنیم، ثبت کنیم. می توان آن را در ماژول ها یا در کامپوننت ها انجام داد . انجام این کار در یک ماژول به Angular اجازه می‌دهد تا سرویس‌های مربوطه را در هر کلاسی که ایجاد می‌کند تزریق کند و بنابراین نمونه Service تا پایان عمر برنامه زنده می‌ماند. با استفاده از ارائه‌دهنده مؤلفه، دامنه سرویس را محدود می‌کنیم و بنابراین فقط به آن نمونه مؤلفه یا یکی از نمونه‌های مؤلفه اصلی آن تزریق می‌شود . این بدان معنی است که Angular نمی تواند همان نمونه سرویس را در جای دیگری تزریق کند. طول عمر این سرویس نیز متفاوت خواهد بود: هنگامی که نمونه Component از بین می رود، نمونه Service از بین می رود.

در اینجا نحوه تزریق یک سرویس در یک مؤلفه آمده است :

فایل logger.service.ts

فایل my-component.component.ts

همچنین می‌توانیم این کار را با ماژول ریشه انجام دهیم :

فایل app.module.tsوارد کردن { Component } از ‘@angular/core’;
وارد کردن { Logger } از ‘./logger’;@Component({
selector: ‘my-component’,
templateUrl: ‘./my-component.component.html’,
})
class export MyComponent Implements OnInit {
constructor(private Logger: Logger {}
}

فایل my-component.component.ts

همچنین می توانیم تصور کنیم که یک سرویس به سرویس دیگری نیاز دارد :وارد کردن { تزریقی } از ‘@angular/core’;
وارد کردن { Logger } از ‘./logger.service’;@Injectable()
export class MyService {
constructor(private logger: Logger) { }
}

اتصال داده ها

اساساً، پیوندهای داده اجازه می‌دهند که ویژگی‌های دو شی به هم مرتبط شوند، به طوری که تغییر در یکی باعث تغییر در دیگری شود. ارتباطی بین رابط کاربری و اپلیکیشن زیربنایی برقرار می کند. این یک رابطه بین دو شی تعریف می کند: یک شی منبع که داده ها را ارائه می دهد و یک شی هدف که از داده های شی منبع استفاده می کند. مزیت اتصال داده این است که دیگر لازم نیست نگران همگام سازی داده ها بین Views و منبع داده خود باشیم.

با Angular ، متداول ترین راه برای نمایش ویژگی Component این است که نام ویژگی را از طریق درون یابی متصل کنید . درون یابی تخمین یک مقدار یا مجموعه ای از ارزش ها بر اساس زمینه آنهاست. این اجازه می دهد تا یک رشته حاوی یک یا چند مکان نگهدار را ارزیابی کنید و آن متغیرهایی را با یک مقدار محاسبه شده و متناظر جایگزین کنید. متن معمولاً نمونه Component است . بنابراین، اساسا، در Angular ، برای رسیدن به این هدف، باید نام ویژگی را در View محصور در پرانتزهای دوتایی قرار دهیم. چیزی شبیه به این خواهد بود:<h1>{{title}}</h1>

اغلب اوقات، اتصالات برای اتصال تصاویر یک برنامه کاربردی با یک مدل داده زیربنایی، معمولاً برای تحقق الگوی MVVM ( Model-View-ViewModel ) یا الگوی MVC ( Mode-View-Controller ) استفاده می شود. در Angular ، کامپوننت بخشی از Controller/ViewModel را بازی می‌کند و الگو نمایانگر View است .

Angular انواع مختلفی از اتصال داده را فراهم می کند . انواع صحافی را می توان به سه دسته تقسیم کرد که با جهت جریان داده از هم متمایز می شوند: منبع به مشاهده ، مشاهده به منبع و توالی دو طرفه: مشاهده به منبع به مشاهده . هنگامی که از انواع اتصال به غیر از درون یابی استفاده می کنیم ، باید یک نام هدف که نام یک ویژگی است را مشخص کنیم. به نظر می رسد یک نام ویژگی است، اما اینطور نیست. با اتصال داده‌ها ، ما با ویژگی‌های HTML کار نمی‌کنیم ، بلکه با ویژگی‌های عناصر DOM ( مدل شیء سند ) کار می‌کنیم. فقط برای تازه کردن ذهن خود، ممکن است بگوییم که ویژگی ها توسط HTML و ویژگی ها توسط DOM تعریف می شوند و مسئولیت ویژگی های HTML فقط مقداردهی اولیه ویژگی های DOM است . ویژگی‌های DOM بعدی می‌توانند تغییر کنند، اما ویژگی‌های HTML نمی‌توانند. برخی از ویژگی های DOM دارای ویژگی های متناظر و برخی از ویژگی های HTML ویژگی های متناظر ندارند. هدف اتصال داده چیزی در DOM است .وارد کردن { Component } از ‘@angular/core’;@Component({
selector: ‘my-component’,
templateUrl: ‘./my-component.component.html’,
})
export class MyComponent {
imgSrc: String = ‘path-to-image’;
}

فایل my-component.component.ts<img [src]=”imgSrc”>

فایل my-component.component.html

ما اغلب می گوییم که اتصال ویژگی یک اتصال داده یک طرفه است زیرا یک مقدار را در یک جهت جریان می دهد، از ویژگی داده کامپوننت به ویژگی عنصر هدف. با این حال، ما مجاز به دستیابی به چیزی به نام اتصال دو طرفه داده هستیم که به عنوان مثال، به ما اجازه می دهد یک ویژگی داده را نمایش دهیم و زمانی که کاربر تغییراتی را ایجاد می کند، آن ویژگی را به روز کنیم. ما می توانیم این کار را با استفاده از نحو ” [(x)] انجام دهیم .

ما همچنین قادر به دستیابی به رویداد الزام آور هستیم:صادرات کلاس MyComponent {
doSomething() {
// مقداری کد
}
}

فایل my-component.component.ts<button (click)=”doSomething()”>کاری انجام دهید</button>

فایل my-component.component.html

ورودی و خروجی

در یک کامپوننت ، می‌توانیم از دو دکوراتور برای ویژگی‌ها استفاده کنیم: ” @Input ” و ” @Output “.

یک ویژگی Input یک ویژگی قابل تنظیم است. یک ویژگی خروجی یک ویژگی قابل مشاهده است. ویژگی های ورودی معمولا مقادیر داده را دریافت می کنند. ویژگی های خروجی تولیدکنندگان رویداد را در معرض دید قرار می دهد .

اعلان یک ویژگی Input چیزی شبیه به این می دهد:export class MyComponent {
@Input() name: String;
}

فایل my-component.component.ts<my-component name=”foo”></my-component>

فایل my-component.component.html

یک ویژگی Output تقریباً همیشه یک Angular EventEmitter را برمی گرداند . یک EventEmitter به ما امکان می دهد یک رویداد سفارشی را منتشر کنیم . ارسال یک مقدار به یک مؤلفه والد مفید است . بیایید بگوییم که ما چیزی شبیه به این داریم:Export class MyComponent {
@Output() deleteItemRequest = new EventEmitter<Item>(); delete() {
this.deleteItemRequest.emit(this.item)
}
}

فایل my-component.component.ts<button (click)=”delete()”>حذف</button>

فایل my-component.component.html

همانطور که می بینیم، در اینجا از رویداد binding استفاده می کنیم. بنابراین، هنگامی که دکمه کلیک می شود، ما متد “ delete() ” را فراخوانی می کنیم. در کامپوننت ، ما همچنین یک ویژگی Output را اعلام می کنیم که یک EventEmitter را برمی گرداند و نوع زیربنایی آن را به عنوان ” Item ” اعلام می کنیم . بنابراین، زمانی که متد “ delete() ” فراخوانی می‌شود، از این EventEmitter برای انتشار یک رویداد جدید استفاده می‌کنیم . در واقع، یک شی ” Item ” منتشر می کند .

بنابراین، اکنون می توانیم تصور کنیم که چیز زیر را به عنوان مولفه والد داریم :Export class ParentComponent {
deleteItem(item: Item) {
// Some code
}
}

فایل parent-component.component.ts<parent-component (deleteItemRequest)=”deleteItem($event)”></parent-component>

فایل parent-component.component.ts

هنگامی که مؤلفه فرزند رویداد خود را منتشر می کند ، مؤلفه والد از نتیجه همان رویداد با روش خاص خود استفاده می کند.

قلاب چرخه حیات اجزا

Angular چرخه عمر کامپوننت های مختلف را مدیریت می کند . از طریق قلاب های مختلف ، راهی برای انجام اقدامات در هنگام وقوع آن لحظات مختلف ارائه می دهد. ما با اجرای یک یا چند رابط Hook چرخه حیات در کتابخانه هسته Angular به آن لحظات دسترسی داریم . هر رابط دارای یک روش Hook است که نام آن نام رابط با پیشوند ” ng ” است.

در زیر، نمونه‌ای از کامپوننت را داریم که از رابط OnInit استفاده می‌کند :Export class MyComponent OnInit {
ngOnInit() {
// مقداری کد
}
} را پیاده سازی می کند

ارتباط بین مؤلفه های والدین و فرزند

چند راه برای ایجاد تعامل مولفه والدین و فرزند وجود دارد . یک راه این است که کامپوننت فرزند را به عنوان ViewChild به والد تزریق کنید . این می تواند به این صورت به دست آید:وارد کردن { ViewChild } از ‘@angular/core’;
وارد کردن { Component } از ‘@angular/core’;
وارد کردن { ChildComponent } از ‘./child-component.component’;export class ParentComponent {
@ViewChild(ChildComponent)
private childComponent: ChildComponent; method1() {
this.childComponent.childMethod1();
} method2() {
this.childComponent.childMethod2();
}
}

راه دیگر برای ایجاد تعامل والدین و مؤلفه فرزند این است که آنها را وادار به اشتراک گذاری یک سرویس کنید .

بخشنامه ها

در انگولار ، سه نوع دستورالعمل وجود دارد :

  • اجزای – دستورالعمل ها با یک الگو
  • دستورالعمل های ساختاری – با افزودن و حذف عناصر DOM ، طرح DOM را تغییر دهید
  • دستورالعمل های ویژگی – ظاهر یا رفتار یک عنصر، مؤلفه یا دستورالعمل دیگر را تغییر می دهد

قبلاً Components را دیده‌ایم . آنها رایج ترین دستورالعمل ها هستند .

دستورالعمل های ساختاری ساختار View را تغییر می دهند . آنها چیزهایی مانند ” NgFor ” یا ” NgIf ” هستند. در اینجا نمونه ای از دستورالعمل های ساختاری مختلف آورده شده است :<div *ngIf=”character” class=”name”>{{character.name}}</div><ul>
<li *ngFor=”اجازه شخصیت کاراکترها”>{{character.name}}</li>
</ul><div [ngSwitch]=”character?.size”>
<app-big-character *ngSwitchCase=”‘big'” [character]=”character”></app-big-character>
<app-medium-character * ngSwitchCase=”‘medium'” [character]=”character”></app-medium-character>
<app-small-character *ngSwitchCase=”‘small'” [character]=”character”></app-small -character>
<app-character *ngSwitchDefault=”‘small'” [character]=”character”></app-character>
</div>

دستورالعمل های ویژگی به عنوان ویژگی های عناصر استفاده می شود. آنها چیزهایی مانند ” NgClass ” یا ” NgStyle ” هستند. در اینجا نمونه ای از دستورالعمل های ویژگی مختلف آورده شده است :<div [ngStyle]=”currentStyles”>
برخی از محتواها.
</div><div [class.error]=”hasError”>برخی خطا</div>

بیایید یک یادداشت جانبی کوچک برای دستورالعمل ” NgModel ” که بخشی از ” FormsModule ” است، ایجاد کنیم. این دستورالعمل به ما کمک می کند زمانی که می خواهیم یک ویژگی داده را نمایش دهیم و زمانی که کاربر از طریق یک فرم تغییراتی ایجاد می کند، آن ویژگی را به روز کنیم. استفاده از این اتصال دو طرفه داده این کار را آسان تر می کند. فیلدهای مختلف فرم ما را به مدل داده ما نگاشت می کند . این اطمینان حاصل می کند که داده های موجود در View و داده های مدل داده ما همگام هستند.

ما می توانیم از این دستورالعمل به این صورت استفاده کنیم:export class MyComponent {
name: string;
}

فایل my-component.component.ts<input type=”text” [(ngModel)]=”name” />

فایل my-component.component.html

ما همچنین قادر به ساخت دستورالعمل های ویژگی هستیم . ما فقط باید یک کلاس ایجاد کنیم که با دکوراتور « @Directive » حاشیه نویسی شده است.

لوله های

لوله ها روشی برای اعمال برخی تبدیل ها بر روی داده ها قبل از نمایش آنها هستند. Angular دارای چندین لوله داخلی است . به عنوان مثال، ما می توانیم چیزی شبیه به این داشته باشیم:<p>تولد شخصیت {{ تولد | date:”MM/dd/YY” }}</p>

ما همچنین می‌توانیم Pipe‌های خود را با استفاده از دکوراتور « @Pipe » و پیاده‌سازی رابط « PipeTransform » ایجاد کنیم. این می تواند به این صورت انجام شود:وارد کردن { Pipe, PipeTransform } از ‘@angular/core’;@Pipe({name: ‘exponentialStrength’})
class export ExponentialStrengthPipe PipeTransform {
transform(value: number, exponent: string): number {
let exp = parseFloat(exponent);
بازگشت Math.pow(value, isNaN(exp) ? 1 : exp);
}
}

قابل مشاهده

Observables برای ارسال پیام بین ناشران و مشترکین در برنامه ما پشتیبانی می کند . یک Observable می تواند چندین مقدار از هر نوع را ارائه دهد.

یک ناشر باید یک نمونه قابل مشاهده ایجاد کند . این شی تابعی را تعریف می کند که زمانی که یک مصرف کننده متد “ subscribe() ” را فراخوانی می کند اجرا می شود. این روش که تابع مشترک نامیده می شود ، نحوه دریافت اطلاعات برای انتشار را بیان می کند. برای اجرای Observable خود ، باید متد “ subscribe() ” آن را فراخوانی کرده و به آن Observer ارسال کنیم . این شیء رابط “ Observer ” را پیاده سازی می کند و مسئول رسیدگی به اعلان های مختلف از Observable است .

برای استفاده از Observables ، باید کتابخانه RxJS را وارد کنیم . RxJS یک کتابخانه برای برنامه نویسی واکنشی است که یک الگوی برنامه نویسی اعلامی است که در آن با جریان های داده ناهمزمان برنامه ریزی می کنیم. جریان‌های داده می‌توانند هر چیزی باشند و ما می‌توانیم به آنها گوش دهیم و مطابق با آن واکنش نشان دهیم. یک جریان دنباله ای از رویدادهای پیوسته است که در زمان مرتب شده اند و می تواند سه چیز مختلف را منتشر کند: یک مقدار از نوع، یک خطا یا یک مقدار ” تکمیل شده “. به طور ناهمزمان، ما این رویدادهای مختلف منتشر شده را با تعریف توابع ضبط می‌کنیم: یکی که با ارسال یک مقدار اجرا می‌شود، دیگری که هنگام گسیل یک خطا اجرا می‌شود و دیگری که با ارسال ” تکمیل ” اجرا می‌شود. عمل گوش دادن به جریان « اشتراک » نام دارد. توابع مختلفی که ما تعریف می کنیم ” مشاهده ” هستند در حالی که جریان “موضوع” یا ” مشاهده ” است. این الگوی طراحی رفتاری است که به آن الگوی مشاهده گر می گویند . ما همچنین باید با « عملگرها » که توابع مختلف خالص هستند، سروکار داشته باشیم، توابعی که همیشه مقدار نتیجه یکسانی را ارزیابی می‌کنند، زمانی که همان مقدار آرگومان را به آنها می‌دهیم، که به ما اجازه می‌دهند روی مقادیر منتشر شده کار کنیم.

این نوع برنامه نویسی زمانی که باید با رویدادهای مختلف رابط کاربری مرتبط با رویدادهای داده سروکار داشته باشیم واقعا مفید است . این به ما کمک می کند تا به برنامه های بلادرنگ دست پیدا کنیم.

بیایید تصور کنیم که ما یک سرویس داریم که مسئول واکشی کاربران است:import { قابل مشاهده } from ‘rxjs/Rx’
import { injectable } from ‘@angular/core’
import { Http, Response } from ‘@angular/http’@Injectable()
export class UsersService { سازنده (http عمومی: Http) {} public fetchUsers() {
return this.http.get(‘/api/users’).map((res: Response) => res.json())
}
}

متد ما “ fetchUsers() ” یک Observable ، موضوع ما را برمی گرداند. بنابراین، می‌توانیم در موضوع خود به این صورت مشترک شویم:import { Component } from ‘@angular/core’
import { Observable } from ‘rxjs/Rx’import { UsersService } from ‘./users.service’
import { User } from ‘./user’@Component({
selector: “my-component”،
templateUrl: “./my-component.component.html”،
ارائه دهندگان: [ UsersService }
)
class export MyComponent {
public users: Observable<User[]> سازنده (public usersServce: UserService) {} public ngOnInit() {
this.users = this.UsersService.fetchUsers()
}
}

در فایل قالب ما باید کارهای زیر را انجام دهیم:<ul class=”user-list” *ngIf=”(users | async).length”>
<li class=”user” *ngFor=”اجازه به کاربر کاربران | async”>
{{ user.name }}
</ li>
</ul>

همچنین ممکن است بخواهیم یک Observable از یک Promise ایجاد کنیم . ما می توانیم این کار را به این صورت انجام دهیم:const data = fromPromise(fetch(‘/api/endpoint’));

این یک Observable ایجاد می کند . برای عضویت باید موارد زیر را انجام دهیم:data.subscribe({
next(response) { console.log(response); },
error(err) { console.error(‘Error: ‘ + err); },
complete() { console.log (‘completed’) ; }
});

در اینجا به فرآیند اشتراک دست پیدا می کنیم و همانطور که می بینیم سه عملکردی را که کمی قبل در مورد آنها صحبت کردیم تعریف می کنیم.

تشکیل می دهد

می‌توانیم از پیوندهای رویداد Angular برای پاسخ به رویدادهایی که توسط ورودی کاربر راه‌اندازی می‌شوند، استفاده کنیم. به عنوان مثال، می توانیم وضعیت زیر را تصور کنیم:صادرات کلاس MyComponent {
مقادیر = ”; onKey(event: any) {
this.values ​​+= event.target.value;
}
}

فایل my-component.component.ts<input (keyup)=”onKey($event)”>
<p>{{values}}</p>

فایل my-component.component.html

Angular همچنین دارای یک کتابخانه کامل ” Form ” است که به ما در بسیاری از موارد کمک می کند. برای مثال می‌توانیم از آن برای اضافه کردن برخی قوانین اعتبارسنجی به فرم‌هایمان استفاده کنیم.<input id=”name” name=”name” class=”form-control” مورد نیاز minlength=”4″ [(ngModel)]=”user.name” #name=”ngModel” ><div *ngIf=”name.invalid && (name.dirty || name.touched)” class=”alert alert-danger”> <div *ngIf=”name.errors.required”>
نام مورد نیاز است.
</div>
<div *ngIf=”name.errors.minlength”>
نام باید حداقل 4 کاراکتر داشته باشد.
</div>
</div>

در اینجا، با تعریف یک ورودی با چند قانون شروع می کنیم. همانطور که می بینیم، دستورالعمل ” ngModel ” را برای دستیابی به اتصال دو طرفه داده صادر می کنیم . ما همچنین وضعیت کنترل فرم را به یک متغیر محلی ” #name ” صادر می کنیم. سپس بررسی می کنیم که آیا کنترل لمس شده است یا خیر و در صورت وجود خطاهای مختلف را نمایش می دهیم.

با Angular ، ما همچنین توانایی تولید پویا فرم ها را داریم. برای دستیابی به این هدف، ما باید اشیایی را ایجاد کنیم که از کلاس پایه ” QestionBase ” مشتق شده اند و کنترل های مختلف فرم های ما را نشان می دهد. سپس می‌توانیم آنها را از طریق سرویسی که فرم را می‌سازد و آن را به عنوان یک شی « FormGroup » برمی‌گرداند، درمان کنیم.

مسیریابی و ناوبری

در Angular ، روتر امکان پیمایش از یک نمای به نمای بعدی را می دهد. روتر یک URL مرورگر را تفسیر می کند تا به نمای ایجاد شده توسط مشتری حرکت کند و در صورت نیاز، پارامترهای اختیاری را ارسال کند. روتر می تواند به پیوندها متصل شود یا می توان از آن در پاسخ به برخی اقدامات استفاده کرد .

برای استفاده صحیح از روتر ، باید یک عنصر “ base ” را به فایل “ index.html ” خود اضافه کنیم. ما همچنین باید ماژول روتر را وارد کنیم . در فایل ” app.module.ts ” ما ، می توانیم کارهای زیر را انجام دهیم:وارد کردن { RouterModule, Routes } از ‘@angular/router’;const appRoutes: Routes = [
{ path: ‘characters’, component: CharactersComponent },
{ path: ‘character/:id’, component: CharacterDetailComponent },
{ path: ”, redirectTo: ‘/characters’, pathMatch: ‘full ‘ },
{ path: ‘**’, component: PageNotFoundComponent }
];@NgModule({
imports: [
RouterModule.forRoot(appRoutes)
]
})
class export AppModule { }

همانطور که می بینیم، مسیرهای ناوبری خود را در آرایه ” appRoutes ” تعریف می کنیم و این آرایه را به ” RouterModule ” منتقل می کنیم. اکنون می‌توانیم از دستورالعمل RouterOutlet استفاده کنیم ، که مشخص می‌کند که روتر یک View را نشان می‌دهد تا نوعی منوی ناوبری ایجاد کنیم:<nav>
<a routerLink=”/characters” routerLinkActive=”active”>شخصیت‌ها</a>
</nav>
<router-outlet></router-outlet>

پس از پایان هر چرخه حیات پیمایش موفق، روتر درختی از اشیاء ” ActivatedRoute ” می سازد که وضعیت فعلی روتر را تشکیل می دهند . ما می‌توانیم با استفاده از Router Service و ویژگی RouterState از هر نقطه در برنامه به ” RouterState ” فعلی دسترسی داشته باشیم.

نتیجه

از طریق این مقاله، مروری کوتاه بر فناوری Angular داشتیم . این بیشتر یک پست تئوری بود تا یک مثال عملی. البته، ما به طور کامل هر موضوع را پوشش ندادیم و بسیاری از موضوعات دیگر مانند تست واحد یا تست E2E وجود دارد که می‌توانستیم آنها را بررسی کنیم . با این حال، اکنون ما دانش کافی از Angular برای شروع یک پروژه و عمیق‌تر کردن این چارچوب داریم.