Angular在组件级别注册提供者

huangapple go评论60阅读模式
英文:

Angular register provider at component level

问题

当你在组件级别注册提供者时,你会在每个该组件的新实例中获得一个新的服务实例。在这个术语中,服务是给定组件对象的一个实例变量,这意味着该服务是它的依赖项。该依赖项可以通过构造函数注入到组件中。

// 相对于下面的工作示例
constructor(private service: HeroService) { }

并由Angular框架管理。在这个上下文中,构造函数注入的行为可以被理解为(伪代码):

class Component {
    private Service service;
    constructor(Service service) {
        this.service = service;
    }
}

这意味着如果创建了一个组件对象,在我们的案例中是HeroList类的一个实例,那么我们将我们的依赖项(HeroService实例)注入(传递)到HeroList构造函数中 (HeroList hl = new HeroList(new HeroService()))。

为什么第2点下的代码没有满足第1点中工作示例的表示/解释?

hero.service.ts

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

@Injectable()
export class HeroService {
  constructor() { }
}

hero-list.component.ts

import { Component } from '@angular/core';
import { HeroService } from '../hero.service';

@Component({
  selector: 'app-hero-list',
  templateUrl: './hero-list.component.html',
  styleUrls: ['./hero-list.component.css'],
  providers: [ HeroService ]
})
export class HeroListComponent {
    constructor(private service: HeroService) { }
}

hero.service.ts

export class HeroService {
  constructor() { }
}

hero-list.component.ts

import { Component } from '@angular/core';
import { HeroService } from '../hero.service';

@Component({
  selector: 'app-hero-list',
  templateUrl: './hero-list.component.html',
  styleUrls: ['./hero-list.component.css'],
})
export class HeroListComponent {
    constructor(private service: HeroService) { }
}

如果我将HeroListComponent类修改为:

export class HeroListComponent {
  private service: HeroService;
  constructor() {
    this.service = new HeroService();
  }
}

那么你也会在每个该组件的新实例中获得一个新的服务实例。这样,我们也满足了组合模式(两个对象之间的“拥有关系”)的要求。

英文:

When you register a provider at the component level, you get a new instance of the service with each new instance of that component. In this term, the service is a instance variable of a given component object that means the service is his dependency. The dependency can be injected into component by constructor injection

//with respect to the working example below
constructor( private service: HeroService ) { }

and is managed by Angular framework. In this context the line of constructor injection can be read as (pseudo code):

class Component {
    private Service service;
	constructor( Service service) { 
      this.service = service;
    }
}

That means if a component object is created, in our case an instance of class HeroList, then we inject(pass) our dependency(HeroService instance) to HeroList constructor (HeroList hl = new HeroList(new HeroService())).

Why code under point 2. does not fulfilled the representation/interpretation of the working example in point 1?

1)
hero.service.ts

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

@Injectable()
export class HeroService {
  constructor() { }
}

hero-list.component.ts

import { Component } from '@angular/core';
import { HeroService } from '../hero.service';

@Component({
  selector: 'app-hero-list',
  templateUrl: './hero-list.component.html',
  styleUrls: ['./hero-list.component.css'],
  providers: [ HeroService ]
})
export class HeroListComponent {
	constructor( private service: HeroService ) { }
}

2)
hero.service.ts

export class HeroService {
  constructor() { }
}

hero-list.component.ts

import { Component } from '@angular/core';
import { HeroService } from '../hero.service';

@Component({
  selector: 'app-hero-list',
  templateUrl: './hero-list.component.html',
  styleUrls: ['./hero-list.component.css'],
})
export class HeroListComponent {
	constructor( private service: HeroService ) { }
}

If I modify HeroListComponent class to:

export class HeroListComponent {
  private service: HeroService;	
  constructor( ) { 
    this.service = new HeroService();
  }
}

then you get also new instance of the service with each new instance of that component. And we fulfilled the composite pattern ("has-a" relationship between two objects) as well.

答案1

得分: 1

第一个方法是有效的方法,而第二个方法则不是。

第一个方法

正如你所解释的那样。你正在为组件范围提供服务(创建一个新实例)。这意味着这个服务实例可以在你的组件及其所有子组件中用作依赖项。

第二个方法

如果这是有意使用 TypeScript 类作为服务而没有使用 @Injectable 装饰器,那么它将无法正常工作。要使其正常工作,你需要在需要它的地方提供该类,例如在你的组件范围内,使用 类提供程序对象 在 providers 数组中如下所示:

providers: [{ provide: HeroService, useClass: HeroService }]

在 Angular 应用程序中,注入器对象 负责创建你的服务的单例实例,并将其作为依赖项提供给你组件的构造函数。此对象需要知道你的服务在哪个范围内可用(提供)才能正确地完成其工作。如果没有这些信息,你将收到编译错误。

英文:

The difference

The first approach is a working approach and the second one is not.

The first approach

As you've explained exactly. You are providing a service (creating a new instance) on the component scope. Wich means this service instance could be used as a dependency in your component and all it's children.

The second approach

If this was on on purpose to use a typescript class as a service without the @Injectable decorator, it will not work this way. To make it work you need to provide the class where it's needed e.g. on your component scope with the help of the class provider object under the providers array like:

providers: [ {provide: HeroService, useClass: HeroService]

In angular application the injector object is responsible for creating a singletone instance of your service and provide it as a dependency in the constructor of your component. This object needs to know on which scope your service is avaliable (provided) to be able to do its job properly. Without this information you will get a compilation error.

答案2

得分: 1

当你在一个类上使用Injectable注解时,你告诉Angular将该类注册为一个service,并可以通过应用程序的依赖注入(DI)提供该类。

另一个类只是一个普通的JavaScript类。当你尝试通过DI来使用它时,你将会得到一个众所周知的错误:

NullInjectorError: No provider for HeroService!

查看此演示中的控制台输出

因此,第一个方法是一个有效的服务,而另一个则不是。

英文:

When you have a class with the Injectable annotation, you are telling Angular to have that class registered as a service and can be provided through the application via dependency injection (DI).

The other one, is just a plain javascript class. When you try to use it via DI, you'll get well known error:

NullInjectorError: No provider for HeroService!

Look at console output in this demo

So the first approach is a valid service, the other one isn't.

huangapple
  • 本文由 发表于 2023年6月26日 03:40:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/76552149.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定