Angular là một nền tảng web framework được phát triển bởi Google. Phiên bản đầu tiên của Angular được công bố vào tháng 10/2010 với tên gọi là AngularJS phát triển dựa trên nền tảng JavaScript với kiến trúc MVC (Model View Controller). Các phiên bản tiếp theo của Angular được đổi tên thành tên phiên bản thay vì sử dụng tên là AngularJS (Angular 2.0; Angular 4.0…) và được phát triển dựa trên TypeScript thay vì JavaScript (tính tới thời điểm của bài viết, phiên bản mới nhất của Angular là phiên bản Angular 12 được công bố tháng 5/2021). Chúng ta có thể coi TypeScript là phiên bản nâng cao của JavaScript vì nó bao gồm các phiên bản ES và bổ sung thêm các kiểu dữ liệu tĩnh, các lớp hướng đối tượng giúp người dùng dễ dàng viết các đoạn code hơn (code viết bằng TypeScript sẽ được biên dịch sang JavaScript).

Để dễ tiếp cận cách thức hoạt động của Angular, chúng ta sẽ tìm hiểu kiến trúc tổng quan của Angular 2 bao gồm 8 thành phần chính là Modules, Components, Templates, Metadata, Data binding, Directives, Services và Dependency injection [1] (Các phiên bản tiếp theo có bổ sung và thay đổi cách sắp sếp các thành phần chính của Angular nhưng nội dung, ý nghĩa và cách thức sử dụng cũng tương tự như Angular 2. Các bạn tham khảo chi tiết tại đây)

1. Modules

Các ứng dụng Angular được phát triển dựa trên việc module hóa và mỗi module là một block thực hiện một chức năng nhất định. Một ứng dụng Angular có thể có một hoặc nhiều modules và các module được khai báo bằng @NgModule decorator với các tham số sau:

– declarations: tên các lớp view thuộc module này (Angular có 3 loại lớp view là: components, directives và pipes).

– exports: tên các lớp view thuộc declarations có thể được sử dụng trong component templates của các modules khác.

– imports: tên các modules sẽ được sử dụng trong module này.

– providers: tên các services mà module này cung cấp.

– bootstrap: tên lớp view dành cho root component, chỉ có root module mới thiết lập tham số này.

Sau đây là một ví dụ về Angular module (các module sẽ có đuôi file là .module.ts như login.module.ts):

2. Component

Component được sử dụng để điều khiển view trong Angular (tương tư như Controller trong mô hình MVC). Các component sẽ có đuôi file là .component.ts như login.component.ts)

3. Template

Template được viết dưới dạng HTML (ngoài việc sử dụng các HTML element như <p>, <h2>, Angular sử dụng các syntax riêng như *ngFor, *ngIf…) giúp hiển thị ứng dụng Angular (các template sẽ có đuôi file là .component.html như login.component.html)

4. Metadata

Metadata (siêu dữ liệu) được sử dụng để hướng dẫn Angular cách thức xử lý một class. Ví dụ như HeroListComponent ở trên chỉ đơn thuần là một class và nó chỉ trở thành một Component khi ta thêm các Metadata cho class này. Việc thêm metadata trong TypeScript được thực hiện bằng cách sử dụng các decorator như @Component, @NgModule, @Inject,…. [2]

Ví dụ ta có thể thêm metadata cho HeroListComponent sử dụng @Component decorator như sau:

– selector (CSS selector): sử dụng selector để chèn component vào trong một template bất kỳ (Lưu ý: ta phải cấu hình export component để đảm bảo các template có thể sử dụng được).

Ví dụ: nếu một đoạn code HTML chứa <hero-list></hero-list>, thì Angular sẽ chèn HeroListComponent view vào giữa 2 tag này.

– templateUrl: khai báo địa chỉ HTML template.

– providers: tên các Services mà component sử dụng.

5. Data binding

Data binding được sử dụng để hỗ trợ việc trao đổi giữa template và component. Angular cung cấp 4 loại data binding là Interpolation, property binding, event binding và two-way data binding.

Ví dụ:

– Interpolation {{}}: hiển thị giá trị của hero.name của component trong <li> element

– Property binding []: truyền giá trị của selectedHero từ parent component sang hero property của HeroDetailComponent

– Event binding (): (click) gọi hàm selectHero() của component khi người dùng thực hiện click chuột

– Two-way data binding [()]: là dạng data binding kết hợp cả property binding và event binding, do đó sử dụng ký hiệu [()]. Ở ví dụ trên, property binding truyền sữ liệu tới input box và khi người dùng thay đổi giá trị của input box thì giá trị này được truyền ngược lại với event binding.

6. Directives

Directives (chỉ thị) được sử dụng để chỉ dẫn cách thức hiển thị của template. Có hai loại directive là structural directive (chỉ thị cấu trúc như ngFor, ngIf, ngSwitch) và attribute directive (chỉ thị thuộc tính như ngModel, ngStyle, ngClass). Các directives này thường xuất hiện trong các element tag tương tự như các thuộc tính của element.

– Structural directive: được sử dụng để thay đổi layout của template bằng cách thêm, xóa hoặc thay đổi các elements.

*ngFor: chỉ dẫn Angular hiển thị mỗi hero trong heroes list

*ngIf: hiển thị HeroDetail component khi selectedHero=True

– Attribute directive: được sử dụng để thay đổi sự hiển thị (appearance) hoặc hành vi (behavior) của một element. Ví dụ như ngModel thay đổi hành vi của input element bằng cách thiết lập giá trị hiển thị của element này.

Lưu ý:

– Directives là một class với @Directive decorator và chúng ta hoàn toàn có thể viết các Directive của riêng mình

– Component cũng là một directive (directive-with-a-template) nhưng trong kiến trúc của Angular thì Component đóng vai trò quan trọng và là thành phần chính của các ứng dụng Angular nên nó được phân tách riêng so với Directive

7. Service

Service được sử dụng để thực hiện một chức năng chuyên biệt nhất định (logging service, data service…) và được sử dụng trong các Component thông qua dependency injection. Thông thường, chúng ta sử dụng @Injectable() decorator để khai báo class là một service (các service sẽ có đuôi file là .service.ts như login.service.ts).

Lưu ý: Angular khuyến cáo nên tận dụng tối đa Service thay vì viết các đoạn code trong Component

8. Dependency injection

Dependency injection là cách thức cung cấp một instance của một class với đầy đủ dependencies mà class này yêu cầu (phần lớn các depencdencies là các services).

Phương thức hoạt động:

– Khi một component muốn sử dụng service, chúng ta sẽ định nghĩa service này tại tham số của constuctor của component đó

– Khi khởi tạo component, Angular sẽ truy vấn tới injector về service mà component yêu cầu. Injector gồm một container chứa các instance của các service đã được tạo ra trước đó. Nếu instance của service được yêu không có sẵn trong Injector, Injector sẽ tạo ra một instance của service đó và thêm vào container trước khi return lại Angular.

Lưu ý: chúng ta phải thực hiện khai báo service trong ít nhất một provider nào đó sử dụng @Injectable() decorator hoặc @NgModule(), @Component()[3]

– Khi sử dụng lệnh ng generate service thì service đó sẽ được khai báo ở mức root. Khi đó Angular chỉ tạo ra một instance của service và dùng chung cho mọi nơi

– Khi chúng ta cấu hình tham số providers tại một module nhất định thì một instance của service sẽ được dùng chung cho toàn bộ component của module đó.

– Khi chúng ta cấu hình tham số provider tại mức component thì đối với mỗi instance mới của component, một instance mới của service sẽ được tạo ra.

 

[1] https://v2.angular.io/docs/ts/latest/guide/architecture.html

[2] https://ultimatecourses.com/blog/angular-decorators

[3] https://angular.io/guide/architecture-services

Tháng Tám 9, 2021
ITechSeeker