Kiến trúc tổng quan của Angular 2/4 - P1

October 1, 2017 (6y ago)

Đôi điều về Angular 2

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à:

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:

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ó đô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:

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