Bài viết được dịch từ: barbarianmeetscoding.com

Cập nhật 14/09/2016: Bài hướng dẫn này cập nhật theo phiên bản mới nhất cuả Angular 2 (Angular 2 Final).

Tại sao bạn cần quan tâm?

JavaScript và thế giới web đã thay đổi nhiều khi Angualr 1 được phát hành. Và Angular 2 đã tận dụng tất cả những lợi thế đó, bao gồm các chuẩn web và kèm theo nhiều cấu trúc mà hiện giờ có sẵn trong JavaScript chẳng hạn như modules, classes, ...

Không chỉ có vậy, nó còn dựa trên những bài học từ các dự án được phát triển trên Angular 1 để cung cấp cho các lập trình viên một trải nghiệm nhất quán và súc tích hơn. Với việc cắt giảm một lượng lớn các khái niệm cần phải hiểu, giúp cho mô hình phát triển và cú pháp dễ học hơn.

Nó cũng nhanh hơn, cung cấp khả năng render ở phía server, chạy đa nền tảng, hỗ trợ các trình duyệt lỗi thời, ...

Tham khảo các khóa học lập trình online, onlab, và thực tập lập trình tại TechMaster

Danh sách các bài viết trong loạt bài này:

Code mẫu

Bạn có thể tải toàn bộ code mẫu ở GitHub repo.

Bắt đầu với Angular 2 và TypeScript

Cách tốt nhất để bắt đầu học Angular 2 và TypeScript là clone ứng dụng starter, một ứng dụng Angular 2 tối giản thiết lập với TypeScript và một mudule loader.

Đừng lo lắng nếu bạn chưa từng sử dụng TypeScript hoặc ES6.

Tôi sẽ giải thích tất cả các tính năng của TypeScript và ES6 cái có thể không quen thuộc với bạn.

TypeScript là một superset của JavaScript và ES6, nó bổ sung thêm các tính năng mới (như decorators), tăng cường thêm cho ngôn ngữ với các khai báo kiểu. Giúp các lập trình viên phát hiện ra các lỗi trước khi chúng xảy ra trong quá trình runtime hoặc cải thiện các công cụ phát triển.

Nếu muốn học ES6, tôi đã viết rất nhiều bài viết về nó. 
Bạn cũng có thể đọc ES6 350 tính năng, bài viết sẽ cung cấp cho bạn một cái nhìn tổng quan về ES6.

Trong bài viết này chúng ta sẽ sử dụng Angular 2 application quickstart được sử dụng trong Angular 2 documentation. Ứng dụng starter này bao gồm Angular 2 và các thiết lập TypeScript, một HTTP server với browser sync sẽ tự động refresh trình duyệt của bạn bất kỳ khi nào bạn cập nhật source code.

Hãy bắt đầu clone ứng dụng bằng cách nhập lệnh sau (bạn cần cài đặt git trước):
 

git clone https://github.com/Vintharas/quickstart.git angular2-get-started

Lệnh trên sẽ clone ứng dụng quickstart vào thư mục angular2-get-started. Cấu trúc thư mục như sau:

// app source code (and specs)
- app                   # your app source code (and specs)
- index.html            # the entry point to your app
- styles.css            # the global styles for your app

// dependencies
- package.json          # the manifest of your app that states all dependencies 
- systemjs.config.js    # system.js modules configuration

// TypeScript configuration
- tsconfig.json         # TypeScript compiler configuration
- typings.json          # typings configuration (for the TS compiler)
- tslint.json           # TypeScript linting configuration

// Testing
- e2e                   # a folder with end to end tests
- karma.conf.js         # karma test runner configuration
- protractor.config.js  # protractor e2e tests configuration
- karma-test-shim.js
- wallaby.js

- .gitignore
- CHANGELOG.md
- LICENSE
- README.md
- Dockerfile
- favicon.ico

Bước tiếp theo là cài đặt các npm dependenies (bạn cần cài đặt node.js và npm trước) gõ lệnh:

npm install

Khi cài đặt hoàn tất, bạn có thể chạy ứng dụng với lệnh npm start. Lệnh này sẽ bắt đầu biên dịch TypeScript, theo dõi sự thay của các file source code, khởi tạo một server và refresh lại trình duyệt bất cứ khi nào các file source code thay đổi.

Bạn có thể dừng server bất kỳ lúc nào bằng cách nhấn tổ hợp phím Ctrl + C.

index.html điểm bắt đầu của ứng dụng

index.html là điểm bắt đầu ứng dụng của bạn vì:

  • Nó bao gồm tất cả các polyfill cần thiết trong thẻ <head>
  • Nó cấu hình việc tải module cho ứng dụng sử dụng System.js
  • Nó thành lập module chính cho ứng dụng của bạn là app
  • Nó cung cấp HTML markup cho ứng dụng của bạn với phần tử custom là <my-app>
<html>
  <head>
    <title>Angular 2 QuickStart</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="styles.css">

    <!-- Polyfills for older browsers, we are using TypeScript/ES6 
         so we need some polyfills for features that are not existent 
         in some browsers  -->
    <script src="node_modules/core-js/client/shim.min.js"></script>

    <script src="node_modules/zone.js/dist/zone.js"></script>
    <script src="node_modules/reflect-metadata/Reflect.js"></script>
    <script src="node_modules/systemjs/dist/system.src.js"></script>

    <!-- 2. Configure SystemJS 
         The systemjs.config.js file contains information
         about the different modules (libraries) that compose the app. 
         External modules like Angular 2 and modules internal to our 
         application that will be defined by us.
     -->
    <script src="systemjs.config.js"></script>
    <script>
      // import the 'app' module to boostrap the application
      System.import('app')
            .catch(function(err){ console.error(err); });
    </script>
  </head>

  <!-- 3. Display the application -->
  <body>
    <my-app>Loading...</my-app>
  </body>
</html>

Khởi tạo ứng dụng của bạn

Trong Angular 1 chúng ta sử dụng ng-app directive để khai báo điểm bắt đầu ứng dụng của mình. Trong Angular 2 chúng ta sử dụng một bootstrapter. SystemJS cấu hình trong file systemjs.config.jsSystem.import('app') trong index.html nói cho SystemJS import module vào ứng dụng 'app' của bạn.

Dưới đây là các dòng nói system.js biết module chính để nạp, trong file app/main.js

// map tells the System loader where to look for things
var map = {
    'app': 'app'
};

// packages tells the System loader how to load when no filename and/or no extension
var packages = {
    'app': { main: 'main.js',  defaultExtension: 'js' },
};

Module là gì?

Một TypeScript/ES6 module là một cách để đóng gói, nhóm, tái sử dụng, phân phối và nạp code trong JavaScript.

Nói chung, một module sẽ chứa code, đóng gói một chức năng cụ thể. Module sẽ phân phối chức năng này tới phần còn lại của ứng dụng bằng cách định nghĩa một loạt exports, sau đó các phần khác của hệ thống có thể import.

Module core của Angular 2 là 'angular2/core' và nó cung cấp cho bạn khả năng truy cập tới các chức năng core như Component.

Module app/main chứa code khởi tạo cho ứng dụng Angular 2  và nó trông như thế này:

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

platformBrowserDynamic().bootstrapModule(AppModule);

Nó import đối tượng platformBrowserDynamic từ module '@angular/platform-browser-dynamic' và gọi hàm bootstrapModule với tham số là AppModule trong module './app.module'.

Có 2 thứ cần chú ý ở đây:

  • Bootstrapter (bộ khởi tạo) '@angular/platform-browser-dynamic' gợi ý rằng bạn có thể chạy ứng dụng Angular 2 trong trình duyệt, web worker, server và khả năng chạy native trong các thiết bị mobile bằng cách sử dụng các bootstrapter khác nhau.
  • Chú ý thứ 2 là import các mudule theo các cách khác nhau. Các module Angular 2 được import bằng tên, và các component của ứng dụng được import bằng cách sử dụng đường dẫn tương đối.

Gọi hàm bootstrapModule với tham số AppModule nói với Angular 2 rằng đây là module chính của ứng dụng.

Chờ chút ... Nhưng Angular 2 module là gì? Tôi nghĩ chúng ta chỉ cần sử dụng các module của ES6!

Các module Angular 2 chỉ là một tiện ích mới cho các lập trình viên, một mức cao hơn của module gồm các module ES6 và tất cả về developer ergonomics. Các module Angular 2 và decorator NgModule giúp chúng ta khai báo tất cả dependencies và các component của ứng dụng tại một nơi.

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

import { AppComponent }  from './app.component';

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ AppComponent ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }

Decorator NgModule nhận một đối tượng với các thông tin sau:

  • Một mảng imports nơi bạn khai báo các module dependencies, như browser, forms, routing hoặc http. BrowserModule được sử dụng ở trên chứa tất cả các dependencies cần thiết để chạy Angular 2 trên trình duyệt.
  • Một mảng declarations nơi bạn khai báo các componet và directive thuộc về module hiện tại.
  • Một mảng bootstrap xác định component gốc, component mà Angular 2 sẽ sử dụng để khởi tạo ứng dụng của bạn.

Trong đoạn code trên chúng ta import một component AppComponent từ module app.componet.ts và thiết lập nó như là gốc của ứng dụng.

Nhưng cái gì là một component?

Component là các khối xây dựng lên ứng dụng Angular 2. Nó biểu diễn một phần có thể tái sử dụng của UI, thường là một một phần tử custom html.

Một component thành lập bởi ít nhất một phần code html cái được biết là template, một class đóng gói dữ liệu và các tương tác với template, và selector (tên phần tử custom html).

Component App trông giống như thế này:

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

@Component({
    selector: 'my-app',
    template: '<h1>My First Angular 2 App</h1>'
})
export class AppComponent { }

Nó có một class AppComponent cái được decorated bởi một vài metadata. Decorator @Component liên kết class với template và selector my-app (Bạn có nhớ phần tử <my-app> trong file index.html?).

Metadata này nói với Angular 2 rằng bất cứ khi nào thấy phần tử html <my-app>, thì sẽ render template này trong bối cảnh của AppComponent class.

Decorator là gì?

Nếu bạn quen thuộc với C# hoặc Java, một decorator làm việc giống như một Attribute.

Nếu không, bạn có thể hình dung một decorator giống như một chức năng áp dụng tới bất kỳ cái gì nó decorates. Trong trường hợp này, Component decorator đính kèm một vài metadata tới AppComponent class.

Muốn học nhiều hơn về decorator? Bạn có thể xem ví dụ này.

Bạn có thể kiểm tra cách liên kết AppComponent class với template. Bằng cách, thêm thuộc tính title tới AppComponent và sử dụng cú pháp Angular 2 interpolation để liên kết nó với view:

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

@Component({
    selector: 'my-app',
    template: '<h1> {{title}} </h1>'

})
export class AppComponent {
    title: String = 'Star Wars PPlz!!!';
}

Nếu bây giờ bạn save file, browser sẽ tự dộng refresh lại và bạn sẽ thấy Star wars PPlz!!! như là title của ứng dụng.

Component đầu tiên của bạn, liệt kê các nhân vật chính trong star wars!

Chúng ta sẽ tạo ra component đầu tiên để hiển thị một danh sách các nhân vật của Star Wars và sẽ bắt đầu với việc tạo dữ liệu để sử dụng.

Chúng ta sẽ tạo một interface là Person trong file person.ts:

export interface Person{
    name: string;
    weight: number;
    height: number;
}

Khai báo kiểu

TypeScript giúp bạn thêm kiểu vào các khai báo biến và hàm. Điều này giúp bạn làm việc tốt hơn với các công cụ như intellisense và bắt các lỗi về kiểu tốt hơn.

Bây giờ chúng ta sẽ tạo ra component đầu tiên PeopleListComponent. Hãy tạo file people-list.component.ts và tạo một class PeopleListComponent:

import { Person } from './person';

export class PeopleListComponent{
  people: Person[] = [
    {name: 'Luke Skywalker', height: 177, weight: 70},
    {name: 'Darth Vader', height: 200, weight: 100},
    {name: 'Han Solo', height: 185, weight: 85},
  ];

}

Class này có thuộc tính people là một mảng các Person.

Tiếp theo chúng ta sẽ biến class thành một component bằng cách thêm decorator @Component:

import { Component } from '@angular/core';
import { Person } from './person';

@Component({
  selector: 'people-list',
  template: `
    <!-- your template here -->
  `
})
export class PeopleListComponent{
  people: Person[] = [
    {name: 'Luke Skywalker', height: 177, weight: 70},
    {name: 'Darth Vader', height: 200, weight: 100},
    {name: 'Han Solo', height: 185, weight: 85},
  ];

}

Bây giờ chúng ta đã có một component có thể render sử dụng <people-list>. Nhưng vẫn cần định nghĩa template của nó, để biểu diễn một danh sách các nhân vật trong star wars.

Giống như ng-repeat trong Angular 1, Angular 2 có *ngFor để lặp lại một phần nhiều lần:

<!-- this is the new syntax for ng-repeat -->
<ul>
  <li *ngFor="let person of people">
    {{person.name}}
  </li>
</ul>

Dấu * trước ngFor biểu thị *ngFor là một structural directive, kiểu directive thêm hoặc xóa các phần tử của DOM. Bạn sẽ sớm chú ý đến cách Angular 2 sử dụng nhiều dấu hiệu trong cú pháp để chuyển tải một ý nghĩa cụ thể, giúp bạn học và hiểu các loại directive khác nhau của framework.

let person tạo một biến template cục bộ (local template variable) chứa một item trong mảng people và gắn với một phần tử <li>.

Đặt mọi thứ cùng nhau chúng ta có:

import { Component } from '@angular/core';
import { Person } from './person';

@Component({
  selector: 'people-list',
  template: `
  <!-- this is the new syntax for ng-repeat -->
  <ul>
    <li *ngFor="let person of people">
     {{person.name}}
    </li>
  </ul>
  `
})
export class PeopleListComponent{
  people: Person[] = [
    {name: 'Luke Skywalker', height: 177, weight: 70},
    {name: 'Darth Vader', height: 200, weight: 100},
    {name: 'Han Solo', height: 185, weight: 85},
  ];

}

Bạn có thấy ký tự xác định chuỗi template trông khá lạ?

Bởi vì nó  là một backtick (`). Backtick được sử dụng để định nghĩa chuỗi template trong ES6. Đây là một tính năng tuyệt vời của ES6, giúp bạn viết các chuỗi trên nhiều dòng và chèn mọi biểu thức trực tiếp trong chuỗi với một cú pháp đơn giản.

Bạn có thể đọc nhiều hơn ở đây.

Bây giờ chúng ta sẽ cập nhật AppComponent để hiển thị danh sách các nhân vật trong Star Wars:

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

@Component({
    selector: 'my-app',
    template: `
    <h1>  {{title}}  </h1>
    <people-list>
    `
})
export class AppComponent {
    title: String = 'Star Wars PPlz!!!';
}

Nhưng, nó không làm việc.

Để có thể sử dụng một component trong một component khác bạn cần khai báo nó với ứng dụng. Bạn có thể làm điều đó trong file app.module.ts:

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

import { AppComponent }  from './app.component';
import { PeopleListComponent } from './people-list.component';

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ AppComponent, PeopleListComponent ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }

Kết luận

Chúng ta đã đề cập nhiều thứ trong bài viết này, Angular 2, TypeScript, modules, SystemJS, bootstrapping, components, decorators, classes và template strings.

Phần tiếp theo sẽ là Refactoring thành services!