Angular2 之 依赖注入

前端之家收集整理的这篇文章主要介绍了Angular2 之 依赖注入前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

依赖注入这部分分为两部分来学习。第一部分自然是官网上的文档,另外一部分,是自己的“血泪时间史”。

之所以称之为“血泪时间史”,是因为在这部分上花费的时间实在是有点多,也就是前面提到过的“时间的教训”,所以在这里要记录下来,避免下次再犯这样的错误

依赖注入

依赖注入是一个用来管理代码依赖的强大模式。

应用程序全局依赖

在这里主要说的是,在应用程序根组件AppComponent中注册那些被应用程序全局使用的依赖提供商。

import { LoggerService }      from './logger.service';
import { UserContextService } from './user-context.service';
import { UserService }        from './user.service';

@Component({
  moduleId: module.id,selector: 'my-app',templateUrl: 'app.component.html',providers: [ LoggerService,UserContextService,UserService ]
})
export class AppComponent {
/* . . . */
}

在@Component元数据的providers数组导入和注册了几个服务,这些服务都是使用类来实现的,所以服务类能充当自己的提供商。==> 泪在providers数组中就算是注册成功了。

我们在根组件中注册了这些服务,所以我们可以在应用程序的任何地方,把它们注入到任何组件和服务的构造函数中去!

@Injectable()

  • @Injectable装饰器只在一个服务类有自己的依赖的时候,才是必不可少的。
@Injectable()
export class UserContextService {
  constructor(private userService: UserService,private loggerService: LoggerService) {
  }
}

这个@Injectable()就是必不可少的。

  • AppComponent类有两个依赖,但它没有@Injectable()。 它不需要@Injectable(),这是因为组件类有@Component装饰器。 在用TypeScript的Angular应用里,有一个单独的装饰器 — 任何装饰器 — 来标识依赖的类型就够了。

把服务作用域限制到一个组件支树

一个组件中注入的服务依赖,会在该组件的所有子组件中可见,而且Angular会把同样的服务实例注入到需要该服务的子组件中。

这刚好在实际工作有遇到这样的例子。

我在sino-base-data-service.component组件中注入了BaseDataService,那么它的所有子组件sino-list.component就都能访问到这个service。

多个服务实例

主要讲的是,在组件级别注入服务,每个组件就能拥有自己独立的service实例。这样就能保证每个组件都有自己的服务。每个组件都有自己的工作状态,与其他组件的服务与状态相隔离,这种我们成为沙盒化。每个服务和组件都在自己的沙盒里运行。

@Optional 和 @Host

当组件申请一个依赖时,Angular从该组件本身的注入器开始,沿着依赖注入器的树往上找,直到找到第一个符合要求的提供商。如果罩杯多就会抛出一个错误

@Optional

当Angular找不到依赖时,@Optional装饰器会告诉Angular继续执行,Angualr会把此注入参数设置为null(而不是默认的抛出错误的行为)。

@Host

该装饰器将把往上搜索的行为截止在宿主组件

使用提供商来定义依赖

  • useValue - 值提供商
  • useClass
  • useExisting
  • useFactory

useValue

通常在单元测试中使用。useValue的值必须是立即定义的。

e.g.

{ provide: Hero,useValue: someHero },{ provide: TITLE,useValue: 'Hero of the Month' },

useClass

useClasst提供商创建并返回一个指令类的新实例。
使用该技术来为公共或默认类提供备选实现。该替代品能实现一个不同的策略,比如拓展默认类或者在测试的时候假冒真实类。

{ provide: HeroService,useClass: HeroService },{ provide: LoggerService,useClass: DateLoggerService },

useExisting - 别名-提供商

使用useExisting,提供商可以把一个令牌映射到另一个令牌上。实际上,第一个令牌是第二个令牌所对应的服务的一个别名,创造了访问同一个服务对象的两种方法

{ provide: MinimalLogger,useExisting: LoggerService },

通过使用别名接口来把一个API变窄,是一个很重要的该技巧的使用例子.

useFactory - 工厂-提供商

useFactory提供商通过调用工厂函数来新建一个依赖对象。

{ provide: RUNNERS_UP,useFactory: runnersUpFactory(2),deps: [Hero,HeroService] }

知识点

  • 令牌 - 使用提供商来定义依赖

我们通常在构造函数里面,为参数指定类型,让Angular来处理依赖注入。该参数类型就是依赖注入器所需的令牌。 Angular把该令牌传给注入器,然后把得到的结果赋给参数。

使用angular的DI系统来获取参数时,必须将该令牌需要依赖的其他服务一并注入。
e.g.
要模拟BaseDataService必须有ModuleConfig

export class CrudModule {
  static forRoot(config: any,routeConfig?: any): ModuleWithProviders {
    return {
      ngModule: CrudModule,providers: [
        BaseDataService,{
          provide: ModuleConfig,useValue: config,},{
          provide: RouteConfig,useValue: routeConfig ? routeConfig : DEFAULT_ROUTE_CONFIG,],};
  }
}
@Injectable()
export class SinoListComponent implements OnInit {
  constructor(
    private config: ModuleConfig,private baseDataService: BaseDataService,) {}
}
  • ng-content

    把对应组件中的内容投影进组件的视图中。

<ion-content> <sino-loading-hint [state]="state" loadingTitle="loading..." needRefresh=true (onVoted)="onVoted($event)"> <h2 class="sino-list-title">{{title}}</h2> <div class="sino-list" *ngFor="let item of datas; let i = index" (click)="toDetail(item,i)"> <h3>{{item.title}}</h3> <p> 来自:{{item.ngDepartmentName}}的发文申请<br/> <span>发送时间:{{item.signDate}}</span> </p> </div> </sino-loading-hint> </ion-content>
<div class="sino-loading"> // 当state为2时,展示sino-loading-hint包裹的内容。上面�� <ng-content class="sino-loading-hint-content" *ngIf="showContent && state ===2"></ng-content> <div class="sino-loading-hint"> <div *ngIf="state ===1 || state === 3 || state === 4" class="sino-loading-hint-word"> <div class="loading" *ngIf="state === 1"> <ion-spinner class="icon" ></ion-spinner> <span>{{loadingTitle}}</span> </div> <span *ngIf="state === 3">{{errorTitle}}</span> <span *ngIf="state === 4">{{nodataTitle}}</span> </div> <div> <button *ngIf="state == 3 && needRefresh" class="button" (click)="refresh()" [disabled]="voted">重新加载</button> <button *ngIf="state == 4 && needRefresh" class="button" (click)="refresh()" [disabled]="voted">刷新</button> </div> </div> </div>
原文链接:https://www.f2er.com/angularjs/148351.html

猜你在找的Angularjs相关文章