Angular中的@Self和@Host装饰器比较

概要

依赖注入是Angular框架的重要组成部分。如果将root模块比作树的根节点,Angular 应用程序有多个依赖注入器,组织成一个与组件树平行的树状结构。每个注入器都会创建依赖的一个单例。

默认情况下,对于依赖注入的对象,Angular会先从当前组件的注入器中开始查找,经历父组件注入器,当前模块注入器和根模块注入器。直到找到需要依赖注入的对象。

@Self和@Host装饰器主要用于大型多团队的开发项目,对上述的依赖注入对象的搜索过程进行限定,避免错误引用。

@Self和@Host装饰器定义上比较类似,本文通过一个获取当前时间的例子,说明他们的区别。

实例说明

定义组件journalist,interview,report和article和模块journalist,其中journalist包含interview组件,interview包含report和article组件。所有组件均在journalist模块下。

report组件的构造函数采用@Self装饰器,article组件采用@Host装饰器修饰。

定义服务类DatetimeService,该类包含方法 getDateTime()获取当前日期和时间。

上述关键代码见附录。

实验1 将DatetimeService放到report和article注入器中

实验结果如下所示,两个组件都可以获取当前时间。
在这里插入图片描述

实验2 将DatetimeService放到父组件interview的注入器中

实验结果如下所示,只有article组件获取到了时间。
在这里插入图片描述

实验3 将DatetimeService放到父组件journalist的注入器中

实验结果同实验2

实验4 将DatetimeService放到journalist模块的注入器中

实验结果同实验2

结论

@Self装饰器规定只能在当前组件的注入器中查找被注入的对象,而@Host装饰器则允许在整个父组件树对应的注入器中查找被注入的对象。

附录

  • journalist模块代码
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { JournalistComponent } from './journalist.component';
import { InterviewComponent } from '../interview/interview.component';
import { ReportComponent } from '../report/report.component';
import { ArticleComponent } from '../article/article.component';
import { DatetimeService } from 'src/app/services/datetime.service';

@NgModule({
  declarations: [
    JournalistComponent,
    InterviewComponent,
    ReportComponent,
    ArticleComponent,
  ],
  imports: [CommonModule],
 // providers: [DatetimeService],
  exports: [
    JournalistComponent,
    InterviewComponent,
    ReportComponent,
    ArticleComponent,
  ],
})
export class JournalistModule {}

  • journalist组件的ts和html代码
import { Component, OnInit, Host, Optional } from '@angular/core';
import { DatetimeService } from 'src/app/services/datetime.service';
@Component({
  selector: 'app-journalist',
  templateUrl: './journalist.component.html',
  styleUrls: ['./journalist.component.scss'],
 // providers: [DatetimeService],
})
export class JournalistComponent implements OnInit {
  constructor() {}
  ngOnInit(): void {}
}

<div class="col-md-6">
  <ng-content></ng-content>
</div>
  • interview组件的ts和html代码
import { Component, OnInit, Host, Optional } from '@angular/core';
import { DatetimeService } from 'src/app/services/datetime.service';

@Component({
  selector: 'app-interview',
  templateUrl: './interview.component.html',
  styleUrls: ['./interview.component.scss'],
   // providers: [DatetimeService],
})
export class InterviewComponent implements OnInit {
  constructor() {}
  ngOnInit(): void {}
}
<ng-content></ng-content>
  • article组件的ts和html代码
import { Component, OnInit, Self, Optional, Host } from '@angular/core';
import { DatetimeService } from 'src/app/services/datetime.service';

@Component({
  selector: 'app-article',
  templateUrl: './article.component.html',
  styleUrls: ['./article.component.scss'],
   // providers: [DatetimeService],
})
export class ArticleComponent implements OnInit {
  ngOnInit(): void {
    throw new Error('Method not implemented.');
  }

  alertClass: string = 'alert-danger';
  alertInfo: string = 'Datetime Service is not loaded in ReportComponent.';
  constructor(
    @Host()
    @Optional()
    private datetimeService: DatetimeService
  ) {
    if (this.datetimeService != null) {
      this.alertClass = 'alert-success';
      this.alertInfo = this.datetimeService.getDateTime();
    }
    this.alertInfo =
      'I am ArticleComponent and using @Host to loacate service. ' +
      this.alertInfo;
  }
}

<div class="alert" [class]="alertClass" role="alert">
  {{ alertInfo }}
</div>
  • report组件的ts和html代码
import { Component, OnInit, Host, Optional, Self } from '@angular/core';
import { DatetimeService } from 'src/app/services/datetime.service';

@Component({
  selector: 'app-report',
  templateUrl: './report.component.html',
  styleUrls: ['./report.component.scss'],
  // providers: [DatetimeService],
})
export class ReportComponent implements OnInit {
  alertClass: string = 'alert-danger';
  alertInfo: string = 'Datetime Service is not loaded in ReportComponent.';
  constructor(
    @Self()
    @Optional()
    private datetimeService: DatetimeService
  ) {
    if (this.datetimeService != null) {
      this.alertClass = 'alert-success';
      this.alertInfo = this.datetimeService.getDateTime();
    }
    this.alertInfo =
      'I am ReportComponent and using @Self to loacate service. ' +
      this.alertInfo;
  }

  ngOnInit(): void {}
}
<div class="alert" [class]="alertClass" role="alert">
  {{ alertInfo }}
</div>
  • DatetimeService代码
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class DatetimeService {
  constructor() {}
  getDateTime() {
    return new Date().toUTCString();
  }
}

请根据具体实验要求开启或关闭代码 providers: [DatetimeService], 本文中所有的css类均来自bootstrap最新版本。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值