Helpex - Trao đổi & giúp đỡ Đăng nhập

Học Angular 2: Hướng dẫn tham quan các anh hùng, Dependency Injection

Bài 5 của hướng dẫn Tour of Heroes giới thiệu các dịch vụ.

Trong một tập gần đây của podcast Cuộc phiêu lưu trong Angular , khách mời Pascal Precht đã đưa ra khuyến nghị rằng các nhà phát triển nên có thói quen luôn áp dụng trình trang trí @Injectable cho một dịch vụ. Lý do đằng sau đề xuất đó là do trình trang trí (@Component, @Injectable, v.v.) gây ra việc phát siêu dữ liệu cần thiết để xác định phân cấp tiêm phụ thuộc và không có tác dụng phụ tiêu cực nào khi thêm trình trang trí @Injectable vào dịch vụ ngay cả khi bản thân dịch vụ đó không có bất kỳ phụ thuộc nào. Hướng dẫn về cơ bản đưa ra cùng một khuyến nghị.

Học Angular 2: Hướng dẫn tham quan các anh hùng, Dependency Injection


Cơ chế tiêm phụ thuộc (DI) được mô tả trong bài bao gồm ba phần:

  • Sử dụng câu lệnh nhập để nhập của tệp / mô-đun dịch vụ.
  • Sử dụng một hàm khởi tạo trong thành phần để gán biến mô-đun được xác định với câu lệnh nhập như một thuộc tính của thành phần.
  • Thêm biến mô-đun được xác định bằng câu lệnh nhập vào danh sách các nhà cung cấp trong thuộc tính siêu dữ liệu "nhà cung cấp" của thành phần, "cung cấp" một phiên bản hoạt động của dịch vụ.

Thoạt nhìn, nó có vẻ là một quá trình dài dòng hơn so với cách tiếp cận Angular 1 trong việc liệt kê các phần phụ thuộc làm đối số cho mô-đun (mặc dù nếu bạn muốn thực hiện bất kỳ sự rút gọn nào, bạn cần ghi lại các phần phụ thuộc trong một mảng nội tuyến hoặc một $ riêng biệt câu lệnh thuộc tính tiêm). Nhưng bạn cũng phải tải các mô-đun của mình đúng cách và tất nhiên, tất cả các tệp JavaScript của bạn có chứa các mô-đun phụ thuộc phải được đưa vào thông qua thẻ <script> trả trước. Với cú pháp này, các câu lệnh nhập cho phép bạn chỉ tải các mô-đun phụ thuộc mà bạn cần cho thành phần cụ thể này.

Tôi nghĩ rằng đó là một cú pháp rõ ràng hơn giúp loại bỏ một số bí ẩn ra khỏi quy trình DI. Là một người thực hiện nhiều mã hóa phía máy chủ, tôi quen thuộc với các hàm tạo, vì vậy đối với tôi, vấn đề là nghĩ đến thuộc tính "nhà cung cấp" của thành phần như các đối số sẽ trở thành một phần của lệnh gọi hàm khởi tạo do trình biên dịch tạo ra. Bạn có thể xem trong đầu ra ES5 để xem kết quả gọi tới hàm tạo được cung cấp bởi một nhà cung cấp "heroService":

var AppComponent = (function () {
    function AppComponent(heroService) {
        this.heroService = heroService;
        this.title = 'Tour of Heroes';
    }

Có hooks vào vòng đời thành phần như ngOnInit cung cấp cho các nhà phát triển quyền kiểm soát bổ sung đối với các thành phần của họ. Với Angular 1, tôi sẽ kết thúc làm việc với các bộ điều khiển mà đôi khi rất khó để phân biệt mã sẽ được thực thi khi bộ điều khiển tải từ mã đã xác định các trình xử lý sự kiện hoặc theo dõi các thay đổi dữ liệu nhất định. ngOnInit sẽ cung cấp một vùng chứa cho mã khởi tạo đó và chạy nó tại một điểm trong vòng đời mà thành phần được "tham gia hoàn toàn".

Với cuộc thảo luận trong bài 3 về cách ngIf phá hủy / xóa nội dung mà nó chứa thay vì chỉ ẩn nó, tôi tò mò muốn biết liệu điều đó có nghĩa là bất kỳ thành phần con nào trong nội dung ngIf được bao bọc đó sẽ tắt ngOnInit mỗi khi nó được khôi phục hay không vào DOM. Vì vậy, tôi đã tạo một HeroSubDetailComponent thực sự đơn giản:

import { Hero } from './hero';
import { Component, Input, OnInit } from '@angular/core';

@Component({
    selector: 'my-hero-subdetail',
    template: `
        <div>
            <span>{{hero.name}} is kinda cool.</span>
        </div>
    `
})

export class HeroSubDetailComponent implements OnInit {
    @Input()
    hero: Hero;

    ngOnInit() {
        console.log( "sub-detail-component initialized" );
    } 
}

... và sau đó thêm nó vào HeroDetailComponent hiện có trong một khối ngIf chỉ đánh giá là true cho anh hùng đầu tiên:

import { HeroSubDetailComponent } from './hero-sub-detail.component';

@Component({
    selector: 'my-hero-detail',
    directives: [ HeroSubDetailComponent ],
    template: `
    <div>
      <h2>{{hero.name}} details!</h2>
      <div>
        <label>id: </label>
        {{hero.id}}
      </div>
      <div>
        <label>name: </label>
        {{hero.name}}
      </div>
      <div *ngIf="hero.id == 11">
        <my-hero-subdetail [hero]="hero"></my-hero-subdetail>
      </div>
  </div>
    `
})

... và như tôi nghi ngờ, mỗi khi HeroSubDetailComponent bị xóa sau đó được thêm lại vào DOM khi tôi nhấp qua các anh hùng khác nhau, nó sẽ kích hoạt ngOnInit trên readd.

Tôi không biết rằng Promises đã được thêm vào dưới dạng cấu trúc gốc trong ES2015 (và do đó trong triển khai mới nhất của TypeScript), vì vậy đó là điều tôi đã học được trong bài học này. Tôi đã thoáng bối rối bởi cách nó được sử dụng mà không khởi tạo phiên bản của nó: rõ ràng phương thức giải quyết () là một phương thức tĩnh , vì vậy trong trường hợp này, khi dữ liệu được mã hóa cứng trong ứng dụng và có sẵn ngay lập tức thì việc này là hợp lý. lộ trình. Nhưng một lưu ý về thực tế là trong một trường hợp sử dụng truyền thống hơn, bạn sẽ khởi tạo một phiên bản Promise có thể được đảm bảo.

5 hữu ích 0 bình luận 3.5k xem chia sẻ

Có thể bạn quan tâm

loading