Bài viết gồm 2 phần, mở đầu cho series giới thiệu về kiến trúc ứng dụng Angular 2. Để xem phần 2, các bạn có thể vào link này.

Đôi điều về Angular2

  • Hiểu đơn giản là một framework để giúp lập trình viên xây dựng các ứng dụng client với HTML và JavaScript/Typescript ...
  • Việc render HTML templates sẽ được thực hiện bởi Angularized-markup, việc cần làm của một developer là viết các component để quản lý template, thêm mới các xử lý logic bên trong các service, đóng gói component và service thành một module.
  • Một ứng dụng Angular2 được chạy dựa trên việc bootstrapping root module vào Angular's bootstrapper.

    Dựa vào sơ đồ kiến trúc trên ta có thể liệt kê ra 8 thành phần chính tạo ra một ứng dụng Angular 2:
  • Module
  • Component
  • Template
  • Metadata
  • Data Binding
  • Service
  • Directive
  • Dependency Injection

Modules


Angular apps sử dụng hệ thống module, hay còn gọi là Angular modules hoặc NgModules.
Trong bài viết này chủ yếu là giới thiệu các modules; Để tìm hiểu sâu hơn xin vui lòng tham khảo Angular modules.
Mỗi ứng dụng Angular đều phải có ít nhất một Angular module class, là root module, hay còn được đặt tên theo quy ước là AppModule.

Trong các ứng dụng nhỏ, đôi khi chỉ có duy nhất 1 module chính là root module , tuy nhiên ở hầu hết các ứng dụng, còn có thêm nhiều feature modules.
Dù là root hay là feature module, thì mỗi class đều có @NgModule decorator.

Decorators là design pattern thường được dùng để thay đổi hành vi, chức năng của JavaScript classes. Angular cung cấp sẵn nhiều decorators gắn các metadata vào các classes để dễ dàng biết được ý nghĩa và cách thức hoạt động.

NgModule là một decorator function (single metadata object) có các thuộc tính mô tả các module. Các thuộc tính quan trọng là:

  • declarations - Khai báo các View classes thuộc về module. Angular có 3 loại view classes: components, directives, pipes.
  • exports - Một tập con của declarations khả dụng trong component templates của các module khác.
  • imports - Các module khác được exported các classes cần thiết bởi component templates được declarations bên trong module này.
  • providers - Tạo ra các global collection of services có thể truy cập ở mọi ngõ ngách của ứng dụng.
  • bootstrap - Main application view, hay còn được gọi là root component, chứa tất cả các app views. Duy nhất root module có thuộc tính bootstrap.

Dưới đây là một * root module* đơn giản:

app/app.module.ts

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@NgModule({
  imports:      [ BrowserModule ],
  providers:    [ Logger ],
  declarations: [ AppComponent ],
  exports:      [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

Trong trường hợp này, thuộc tính export của AppComponent chỉ đơn giản mô tả cách export; nó thì không cần thiết trong thực tế. Một root module không có lý do gì để export bất cứ điều gì, đơn giản là các component khác ko cần thiết phải import root module.

Khởi chạy ứng dụng bằng cách bootstrapping root module. Trong quá trình development, chúng ta sẽ bootstrap AppModule trong file main.ts.

app/main.ts

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';

platformBrowserDynamic().bootstrapModule(AppModule);

Angular modules vs. JavaScript modules

Angular Module: Class decorator với @NgModule — đây là 1 một tính tăng cơ bản Angular.

Javascript Module: JavaScript cũng có một hệ thống module để quản lý các JavaScript objects. Nó hoàn toàn khác biệt và không liên quan tới Angular module system.

Trong JavaScript mỗi file là một module và tất cả các đối tượng được định nghĩa trong file đều thuộc về module đó. Các module khai báo đối tượng public bằng cách sử dụng từ khóa export. Các module JavaScript khác sử dụng từ khóa import để truy cập vào đối tượng public từ các module khác.

import { NgModule }     from '@angular/core';
import { AppComponent } from './app.component';
export class AppModule { }

Tìm hiểu thêm về Javascript Module.

Angular libraries

Angular được ví như 1 con tàu chuyên chở các JavaScript modules. Cũng có thể ví là các library modules.

Mỗi Angular library name đều bắt đầu với tiền tố @angular.
Bạn cài đặt chúng với npm package manager và import các phần lại bằng câu lệnh JavaScript import.

Lấy ví dụ, import Angular's Component decorator từ @angular/core library như sau:

import { Component } from '@angular/core';

Bạn cũng có thể import Angular modules từ Angular libraries sử dụng câu lệnh JavaScript import:

import { BrowserModule } from '@angular/platform-browser';

Trong ví dụ về root module bên trên, application module cần BrowserModule. Để truy cập tới BrowserModule, ta thêm vào @NgModule metadata imports:

imports:      [ BrowserModule ],

Theo cách này, ta đang sử dụng cả Angular and JavaScript module systems cùng nhau.

Components


Một component điều khiển từng chức năng trên màn hình view.
Ví dụ, view sau được điều khiển bởi các components:

  • The app root với navigation links.
  • The list of heroes.
  • The hero editor.

Chúng ta cần định nghĩa component's application logic—những gì sẽ support trên view—bên trong một class. Class sẽ tương tác với view thông qua API của các properties và methods.

Ví dụ, HeroListComponent có một heroes property trả về 1 mảng các heroes lấy từ service. HeroListComponent cũng có sẵn phương thức selectHero() để get các thuộc tính của selectedHero khi người dùng chọn user từ danh sách.

app/hero-list.component.ts (class)

export class HeroListComponent implements OnInit {
  heroes: Hero[];
  selectedHero: Hero;

  constructor(private service: HeroService) { }

  ngOnInit() {
    this.heroes = this.service.getHeroes();
  }

  selectHero(hero: Hero) { this.selectedHero = hero; }
}

Angular creates, updates, và destroys components cùng với user di chuyển xuyên suốt trong application. App có thể lấy các action ở từng thời điểm tron lifecycle thông qua lifecycle hooks, như ngOnInit() được khai báo bên trên.

Templates


Chúng ta định nghĩa component's view với template của nó. Một template là mã code HTML giúp Angular render component.

Một template có thể có đôi chút khác biệt với HTML thông thường, đây là 1 ví dụ cho template của HeroListComponent:

app/hero-list.component.html

<h2>Hero List</h2>
<p><i>Pick a hero from the list</i></p>
<ul>
  <li *ngFor="let hero of heroes" (click)="selectHero(hero)">
    {{hero.name}}
  </li>
</ul>
<hero-detail *ngIf="selectedHero" [hero]="selectedHero"></hero-detail>

Mặc dù template này sử dụng các thành phần cơ bản HTML như <h2><p>, nhưng cũng có ddôi chút khác biệt như *ngFor,{{hero.name}}, (click), [hero], và <hero-detail> sử dụng Angular's template syntax.

Trên dòng cuối cùng của template, <hero-detail> tag là custom element thể hiện cho new component, HeroDetailComponent.

HeroDetailComponent là một component khác với HeroListComponent chúng ta đang xem. HeroDetailComponent mô tả chi tiết từng hero, mà người dùng đã select từ HeroListComponent. HeroDetailComponent là con(child) của HeroListComponent.

Element <hero-detail> có thể được code thoải mái giữa native HTML elements

Metadata


Metadata giúp Angular biết cách xử lý các class.

Quay trở lại code HeroListComponent bên trên, ta thấy rằng đó chỉ đơn giản là 1 class, ko có dấu ấn gì của 1 framework cả, no "Angular" omg

Thực tế, HeroListComponent thực chất chỉ là 1 class. Nó không phải là 1 component cho tới khi ta khai báo nó với Angular.

Để khai báo với Angular rằng HeroListComponent là 1 component, ta sẽ gắn thẻ metadata vào class này.

Trong TypeScript, việc gắn thẻ metadata sử dụng decorator. Dưới đây là metadata cho HeroListComponent:

app/hero-list.component.ts (metadata)

@Component({
  moduleId: module.id,
  selector:    'hero-list',
  templateUrl: 'hero-list.component.html',
  providers:  [ HeroService ]
})
export class HeroListComponent implements OnInit {
/* . . . */
}

Decorator ở đây chính là @Component, định nghĩa class ngay bên dưới như một component class.

@Component decorator khởi tạo một object với các thông tin mà Angular cần thể tạo và biểu diễn một component & view.

Dưới đây là một số option cấu hình cho @Component:

  • moduleId: Tập hợp các source dựa trên address (module.id) với module-relative URLs như templateUrl.
  • selector: CSS selector ra lệnh cho Angular create và insert một thể hiện component khi nó tìm thấy <hero-list> tag trong parent HTML. Ví dụ, nếu một app's HTML có chứa <hero-list></hero-list>, thì Angular sẽ inserts một instance của HeroListComponent view giữa các tags.
  • templateUrl: module-relative address của component's HTML template.
  • providers: Mảng các dependency injection providers cho services cần thiết để component hoạt động. Đây là 1 cách khai báo với Angular rằng, component's constructo yêu cầu 1 HeroService để nó có thể thu được danh sách các heroes phục vụ việc hiển thị lên màn hình.

Metadata trong @Component giúp Angular biết cách lấy những thành phần chính tạo nên component.
Template, Metadata, và Component được sử dụng cùng với nhau với mục đích tạo nên View.
Ngoài @Component, chúng ta còn có @Injectable, @Input, và @Output là những decorators rất hay được sử dụng.

Tham khảo

https://angular.io/docs/ts/latest/guide/architecture.html