2015-11-28 44 views
15

Tôi có lớp sau ModuleWithHttp:Làm thế nào để mở rộng một thành phần với tiêm phụ thuộc trong Angular 2?

@Injectable() 
export default class { 
    constructor(private fetchApi: FetchApi) {} 
} 

và tôi muốn sử dụng nó như sau:

@Component({ 
    selector: 'main', 
    providers: [FetchApi] 
}) 
export default class extends ModuleWithHttp { 
    onInit() { 
    this.fetchApi.call(); 
    } 
} 

nên bằng cách mở rộng một lớp siêu mà đã tiêm một sự phụ thuộc tôi muốn có quyền truy cập vào nó ở trẻ em của nó.

Tôi đã thử nhiều cách khác nhau, thậm chí có siêu hạng như một thành phần:

@Component({ 
    providers: [FetchApi] 
}) 
export default class { 
    constructor(private fetchApi: FetchApi) {} 
} 

Nhưng vẫn còn, this.fetchApinull, ngay cả trong siêu lớp.

+0

Bạn cần phải tiêm FetchApi vào lớp kế thừa, nhưng nếu nó giúp, bạn có thể truy cập nó từ một cái gì đó lớp cơ sở làm như '( this) .fetchapi.call (...)' (bạn không cần phải chuyển nó qua 'super()'. – rinogo

Trả lời

23

Bạn cần phải tiêm fetchAPI trong lớp siêu và vượt qua nó đến các tầng lớp trẻ

export default class extends ModuleWithHttp { 

    constructor(fetchApi: FetchApi) { 
    super(fetchApi); 
    } 

    onInit() { 
    this.fetchApi.call(); 
    } 
} 

Đây là một tính năng của cách DI hoạt động nói chung. Lớp siêu sẽ khởi tạo con thông qua kế thừa, nhưng bạn phải cung cấp các tham số cần thiết cho con.

+0

Đây cũng là những gì tôi đọc.Tôi muốn trừu tượng DI để tránh toàn bộ bản mẫu này, nhưng tôi thấy rằng tôi cần nhập khẩu, tiêm và mở rộng các lớp con theo cách tương tự. – squixy

+1

Tôi không hiểu điều này. Bởi "lớp cơ sở" bạn có nghĩa là "lớp dẫn xuất" (thường là "lớp cơ sở" sẽ giống như "siêu lớp")? Trường hợp trong ví dụ của bạn là 'fetchAPI' được" thông qua "? Bạn có nói rằng nếu tôi xây dựng một lớp dẫn xuất mới thì các phép tiêm được gọi trong lớp cha sẽ được tạo ra? –

+3

_ "Đây là một tính năng như thế nào DI hoạt động nói chung" _ - nói chung trong góc cạnh, nhưng không nói chung ở khắp mọi nơi. Nhiều khung công tác hỗ trợ DI thông qua các thuộc tính ràng buộc. – Qwertiy

53

Nếu bạn muốn tránh điều này "tấm nồi hơi" mã dịch vụ trong các lớp con tiêm chỉ để tiêm trong constructor lớp cha và sau đó sử dụng hiệu quả các dịch vụ trong các lớp con thông qua thừa kế, bạn có thể làm điều này:

chỉnh sửa: từ góc 5.0.0 ReflectiveInjector đã phản đối ủng hộ StaticInjector, dưới đây được cập nhật mã để phản ánh sự thay đổi này

có một bản đồ dịch vụ với DEPS,

export const services: {[key: string]: {provide: any, deps: any[], useClass?: any}} = { 
    'FetchApi': { 
    provide: FetchApi, 
    deps: [] 
    } 
} 

Có một chủ Injector,

import {Injector} from "@angular/core"; 

export class ServiceLocator { 
    static injector: Injector; 
} 

set nó lên trong AppModule,

@NgModule(...) 
export class AppModule { 
    constructor() { 
    ServiceLocator.injector = Injector.create(
     Object.keys(services).map(key => ({ 
     provide: services[key].provide, 
     useClass: services[key].provide, 
     deps: services[key].deps 
     })) 
    ); 
    } 
} 

sử dụng các vòi phun trong lớp cha mẹ,

export class ParentClass { 

    protected fetchApi: FetchApi; 

    constructor() { 
    this.fetchApi = ServiceLocator.injector.get(FetchApi); 
    .... 
    } 
} 

và mở rộng tầng lớp phụ huynh, do đó bạn không cần tiêm dịch vụ FetchApi.

export class ChildClass extends ParentClass { 
    constructor() { 
    super(); 
    ... 
    } 

    onInit() { 
    this.fetchApi.call(); 
    } 
} 
+0

Làm thế nào tôi có thể tiêm dịch vụ từ trẻ em và sử dụng nó từ cha mẹ? –

+0

Tôi nghĩ rằng bạn không thể và nó không có ý nghĩa với tôi. Trường hợp sử dụng của bạn là gì? –

+3

Tôi với Petr - theo như tôi biết, các lớp cha mẹ không hề biết gì về các lớp con của chúng. Điều đó giống như nhân vật của Roy Scheider từ Jaws biết chuyện gì sẽ xảy ra với Michael Caine trong Jaws: The Revenge. Và tôi nhấn mạnh đây là một sự tương tự hoàn hảo. – SilithCrowe

3

Có thể đáp ứng muộn, nhưng tôi đã giải quyết chỉ tiêm bộ phun trên BaseComponent và trong tất cả các lớp con, theo cách đó tôi không cần duy trì bộ định vị dịch vụ.

cơ sở lớp của tôi:

constructor(private injectorObj: Injector) { 

    this.store = <Store<AppState>>this.injectorObj.get(Store); 
    this.apiService = this.injectorObj.get(JsonApiService); 
    this.dialogService = this.injectorObj.get(DialogService); 
    this.viewContainerRef = this.injectorObj.get(ViewContainerRef); 
    this.router = this.injectorObj.get(Router); 
    this.translate = this.injectorObj.get(TranslateService); 
    this.globalConstantsService = this.injectorObj.get(GlobalConstantsService); 
    this.dialog = this.injectorObj.get(MatDialog); 
    this.activatedRoute = this.injectorObj.get(ActivatedRoute); 
} 

My Lớp trẻ em:

constructor(private injector: Injector) { 

    super(injector); 

} 
Các vấn đề liên quan