Javascript 什么';在angular 2(Beta版)中,将一个服务注入另一个服务的最佳方式是什么?

Javascript 什么';在angular 2(Beta版)中,将一个服务注入另一个服务的最佳方式是什么?,javascript,angular,Javascript,Angular,我知道如何将服务注入组件(通过@component),但如何使用DI在组件之外传递服务 换句话说,我不想这样做: export class MyFirstSvc { } export class MySecondSvc { constructor() { this.helpfulService = new MyFirstSvc(); } } export class MyThirdSvc { constructor() { this.

我知道如何将服务注入组件(通过@component),但如何使用DI在组件之外传递服务

换句话说,我不想这样做:

export class MyFirstSvc {

}

export class MySecondSvc {
    constructor() {
        this.helpfulService = new MyFirstSvc();
    }
}

export class MyThirdSvc {
    constructor() {
        this.helpfulService = new MyFirstSvc();
    }
}
  • 将您的服务“提供”到您打算使用它们的位置或更高的位置,例如,如果您只需要每个服务的一个实例(单实例),您可以使用
    bootstrap()
    将它们放在应用程序的根目录下
  • 在依赖于其他服务的任何服务上使用
    @Injectable()
    装饰器
  • 将其他服务注入依赖服务的构造函数中
boot.ts

import {bootstrap} from 'angular2/platform/browser';
import {AppComponent} from './app.component';
import {MyFirstSvc} from '../services/MyFirstSvc';
import {MySecondSvc} from '../services/MySecondSvc';

bootstrap(AppComponent, [MyFirstSvc, MySecondSvc]);
MySecondSvc.ts

import {Injectable} from 'angular2/core';
import {MyFirstSvc} from '../services/MyFirstSvc';

@Injectable()
export class MySecondSvc {
  constructor(private _firstSvc:MyFirstSvc) {}
  getValue() {
    return this._firstSvc.value;
  }
}
有关其他文件,请参见


服务DI有点奇怪的是,它仍然依赖于组件。例如,
MySecondSvc
是在组件请求时创建的,这取决于组件树中“提供”了
MyFirstSvc
的位置,这可能会影响将哪个
MyFirstSvc
实例注入
MySecondSvc
。此处将对此进行详细讨论:

服务被认为是在组件之间共享的。假设我有一个服务,我可以在不同的组件中使用它

在这个回答中,我向您展示了一个服务,它接受来自一个组件的数据,并将数据发送到另一个组件

我使用了路由、共享服务、共享对象的概念。 我希望这将有助于您了解共享服务的基本原理

注意:@Injectable装饰器用于使服务可注入

Boot.ts

import {Component,bind} from 'angular2/core';

import {bootstrap} from 'angular2/platform/browser';

import {Router,ROUTER_PROVIDERS,RouteConfig, ROUTER_DIRECTIVES,APP_BASE_HREF,LocationStrategy,RouteParams,ROUTER_BINDINGS} from 'angular2/router';

import {SharedService} from 'src/sharedService';

import {ComponentFirst} from 'src/cone';
import {ComponentTwo} from 'src/ctwo';


@Component({
  selector: 'my-app',
  directives: [ROUTER_DIRECTIVES],
  template: `
    <h1>
      Home
    </h1> 

    <router-outlet></router-outlet>
      `,

})

@RouteConfig([
  {path:'/component-first', name: 'ComponentFirst', component: ComponentFirst}
  {path:'/component-two', name: 'ComponentTwo', component: ComponentTwo}

])

export class AppComponent implements OnInit {

  constructor(router:Router)
  {
    this.router=router;
  }

    ngOnInit() {
    console.log('ngOnInit'); 
    this.router.navigate(['/ComponentFirst']);
  }



}

    bootstrap(AppComponent, [SharedService,
    ROUTER_PROVIDERS,bind(APP_BASE_HREF).toValue(location.pathname)
    ]);

是的,第一件事是在要注入的每个服务上添加
@Injectable
装饰器。事实上,
可注入的
名称有点阴险。这并不意味着该类将是“可注入的”,但它将进行修饰,以便可以注入构造函数参数。有关更多详细信息,请参阅此github问题:

以下是我对注入机制的理解。为类设置
@Injectable
装饰器时,Angular将尝试为当前执行链的注入器中的相应类型创建或获取实例。事实上,对于Angular2应用程序,不仅有一个喷油器,还有一个喷油器树。它们与整个应用程序和组件隐式关联。这一级别的一个关键特性是,它们以分层方式链接在一起。此喷油器树映射了部件树。没有为“服务”定义喷油器

我们来取样吧。本人有以下申请:

  • Component
    AppComponent
    :在
    bootstrap
    函数中创建Angular2应用程序时提供的我的应用程序的主要组件

    @Component({
      selector: 'my-app', 
        template: `
          <child></child>
        `,
        (...)
        directives: [ ChildComponent ]
    })
    export class AppComponent {
    }
    
  • 两个服务,
    Service1
    Service2
    Service1
    子组件使用,
    Service2
    Service1

    @Injectable()
    export class Service1 {
      constructor(service2:Service2) {
        this.service2 = service2;
      }
    
      getData() {
        return this.service2.getData();
      }
    }
    

以下是所有这些要素及其关系的概述:

Application
     |
AppComponent
     |
ChildComponent
  getData()     --- Service1 --- Service2
在这种应用中,我们有三个喷油器:

  • 可使用
    引导功能的第二个参数配置的应用程序注入器
  • 可使用此组件的
    providers
    属性配置的
    AppComponent
    喷油器。它可以“查看”应用程序中定义的元素。这意味着,如果在此提供程序中找不到提供程序,将自动在此父注入器中查找该提供程序。如果未在后者中找到,将抛出“未找到提供程序”错误
  • ChildComponent
    喷油器将遵循与
    AppComponent
    喷油器相同的规则。要注入为组件执行的注入链中涉及的元素,将首先在此注入器中查找提供者,然后在
    AppComponent
    中查找提供者,最后在应用程序中查找提供者
这意味着当尝试将
Service1
注入
ChildComponent
构造函数时,Angular2将查看
ChildComponent
注入器,然后查看
AppComponent
注入器,最后查看应用程序注入器

由于需要将
Service2
注入
Service1
,因此将执行相同的解析处理:
ChildComponent
注入器、
AppComponent
一个和应用程序一个

这意味着可以使用组件的
providers
属性和应用程序的
bootstrap
功能的第二个参数,根据需要在每个级别指定
Service1
Service2

这允许共享一组元素的依赖项实例:

  • 如果在应用程序级别定义提供程序,则创建的相应代码实例将由整个应用程序(所有组件、所有服务等)共享
  • 如果在组件级别定义提供者,则该实例将由组件本身、其子组件以及依赖关系链中涉及的所有“服务”共享
所以它非常强大,你可以根据自己的需要自由组织

下面是相应的plunkr,您可以使用它:

Angular2文档中的此链接可以帮助您:

希望它能帮助你(很抱歉回答太长),
Thierry在Angular2.0.0-beta.17中,当连接组件A->ServiceB->ServiceC时,不知何故@Injectable不适合我

我采取了这种做法:

  • 引用@ComponentA的providers字段中的所有服务
  • 在ServiceB中,使用构造函数中的@Inject注释连接ServiceC
  • 运行以查看下面的示例或查看代码

    app.ts

    @Component({selector: 'my-app',
        template: `Hello! This is my app <br/><br/><overview></overview>`,
        directives: [OverviewComponent]
    })
    class AppComponent {}
    
    bootstrap(AppComponent);
    
    概述-service.ts

    import {PropertiesService} from "./properties-service";
    import {Inject} from 'angular2/core';
    
    export class OverviewService {
    
        private propertiesService:PropertiesService;
    
        // Using @Inject in constructor
        constructor(@Inject(PropertiesService) propertiesService:PropertiesService){
            this.propertiesService = propertiesService;
        }
    
        logHello(){
            console.log("hello");
            this.propertiesService.logHi();
        }
    }
    
    // Using @Injectable here doesn't make a difference
    export class PropertiesService {
    
        logHi(){
            console.log("hi");
        }
    }
    
    属性-service.ts

    import {PropertiesService} from "./properties-service";
    import {Inject} from 'angular2/core';
    
    export class OverviewService {
    
        private propertiesService:PropertiesService;
    
        // Using @Inject in constructor
        constructor(@Inject(PropertiesService) propertiesService:PropertiesService){
            this.propertiesService = propertiesService;
        }
    
        logHello(){
            console.log("hello");
            this.propertiesService.logHi();
        }
    }
    
    // Using @Injectable here doesn't make a difference
    export class PropertiesService {
    
        logHi(){
            console.log("hi");
        }
    }
    

    首先要做的是注释所有的ser
    @Component({selector: 'my-app',
        template: `Hello! This is my app <br/><br/><overview></overview>`,
        directives: [OverviewComponent]
    })
    class AppComponent {}
    
    bootstrap(AppComponent);
    
    import {Component, bind} from 'angular2/core';
    import {OverviewService} from "../services/overview-service";
    import {PropertiesService} from "../services/properties-service";
    
    @Component({
        selector: 'overview',
        template: `Overview listing here!`,
        providers:[OverviewService, PropertiesService] // Include BOTH services!
    })
    
    export default class OverviewComponent {
    
        private propertiesService : OverviewService;
    
        constructor( overviewService: OverviewService) {
            this.propertiesService = overviewService;
            overviewService.logHello();
        }
    }
    
    import {PropertiesService} from "./properties-service";
    import {Inject} from 'angular2/core';
    
    export class OverviewService {
    
        private propertiesService:PropertiesService;
    
        // Using @Inject in constructor
        constructor(@Inject(PropertiesService) propertiesService:PropertiesService){
            this.propertiesService = propertiesService;
        }
    
        logHello(){
            console.log("hello");
            this.propertiesService.logHi();
        }
    }
    
    // Using @Injectable here doesn't make a difference
    export class PropertiesService {
    
        logHi(){
            console.log("hi");
        }
    }
    
    @Injectable()
    export class MyFirstSvc {
    
    }
    
    @Injectable()
    export class MySecondSvc {
        constructor(helpfulService: MyFirstSvc) {        
        }
    }
    
    @Injectable()
    export class MyThirdSvc {
        constructor(helpfulService: MyFirstSvc) {        
        }
    }
    
    import { Component } from "@angular/core"
    import { DataService } from "./data.service"
    @Component({
        selector:"test-component",
        template:`<ul>
                 <li *ngFor="let person of persons">{{ person.name }}</li>
                 </ul>
    })
    
    export class TestComponent {
      persons:<Array>;
      constructor(private _dataService:DataService){
        this.persons = this._dataService.getPersons()
      }
    }
    
    export class DataService {
    
    persons:<Array>;
    
    constructor(){
        this.persons = [
          {name: "Apoorv"},
          {name: "Bryce"},
          {name: "Steve"}
        ]
    }
    
    getPersons(){
    
    return this.persons
    
    }
    
    import { Http } from '@angular/http';
    export class DataService {
    
    persons:<Array>;
    
    constructor(){
        this.persons = [
          {name: "Apoorv"},
          {name: "Bryce"},
          {name: "Steve"}
        ]
    }
    
    getPersons(){
    
    return this.persons
    
    }
    
    bootstrap(AppComponent,[MyFirstSvc]);
    
    @Component({
        ...
          providers:[MyFirstSvc]
    }
    ...
    
    export class MySecondSvc {
          constructor(private myFirstSvc : MyFirstSvc ){}
    }