• [Angular] Control the dependency lookup with @Host, @Self, @SkipSelf and @Optional


    Very differently to AngularJS (v1.x), Angular now has a hierarchical dependency injector. That allows to specify service definitions as well as the service lifetime at various levels in our application. Whenever a service is requested, Angular will walk up the component tree and search for a matching definition. While in most cases that's perfectly fine, often you may want to take control over the dependency lookup. In this lesson we will learn how, by applying"@Host, @Self()@SkipSelf() and @Optional().

    @Optional:

    When using @Optional, it set logger to null if the LoggerService is not provided instead of error out.

    export class PersonComponent implements OnInit {
      constructor(
        @Optional()
        public logger: LoggerService
      ) {}
    
      ngOnInit() {}
    
      doLog() {
        if (this.logger) {
          this.logger.log('Message from PersonComponent');
        } else {
          console.log('sorry, no logger available');
        }
      }
    }

    @SkipSelf:

    If child component and parent component both using the same provider and we want to skip using child component's provider instead using parent's provider.

    // Child
    @Component({
      selector: 'app-person',
      template: `
        <div style="border:1px;">
          <p *ngIf="logger === null">I don't have a logger</p>
          <button (click)="doLog()">write log</button>
        </div>
      `
       providers: [
         {
           provide: LoggerService,
           useFactory: loggerFactory('PersonComponent')
         }
       ]
    })
    export class PersonComponent implements OnInit {
      constructor(
        @SkipSelf()
        @Optional()
        public logger: LoggerService
      ) {}
    
      ngOnInit() {}
    
      doLog() {
        if (this.logger) {
          this.logger.log('Message from PersonComponent');
        } else {
          console.log('sorry, no logger available');
        }
      }
    }
    // parent
    
    @Component({
      selector: 'app-root',
      template: `
        <h1>Angular Services</h1>
        <app-person></app-person>
      `,
      providers: [
        {
          provide: LoggerService,
          useFactory: loggerFactory('AppComponent')
        }
      ]
    })
    export class AppComponent {}

    SO in the end 'AppComponent ...' log message will appear in the console.

    @Self():

    Only using the provider for its own component.

    @Component({
      selector: 'app-person',
      template: `
        <div style="border:1px;">
          <p *ngIf="logger === null">I don't have a logger</p>
          <button (click)="doLog()">write log</button>
        </div>
      `
      // providers: [
      //   {
      //     provide: LoggerService,
      //     useFactory: loggerFactory('PersonComponent')
      //   }
      // ]
    })
    export class PersonComponent implements OnInit {
      constructor(
        @Self()
        @Optional()
        public logger: LoggerService
      ) {}
    
      ngOnInit() {}
    
      doLog() {
        if (this.logger) {
          this.logger.log('Message from PersonComponent');
        } else {
          console.log('sorry, no logger available');
        }
      }
    }

    So if PersonComponent has provider defined, it will use its own provider and will not continue searching parent component. 

    Often @Self can use togerther with @Optional, so if the provider is not defined, then set it to null.

    @Host:

    When we have directive, we might need to use @Host.

    @Component({
      selector: 'my-comp',
      ...
      providers: [
         MyService // Must have, other directive cannot find it, throw error.
      ]  
    })
    <my-comp highlighted />
    @Directive({
      selector: 'highlighted'
    })
    export class Hightlighted {
      // Use the provide inject directly into the host component
      constructor (@Host private myService: MyService) {}
    }

    Because we cannot ensure that host element must have the Injection, if not, Angular will throw error, to prevent that, @Host normally work with @Optional together.

    @Directive({
      selector: 'highlighted'
    })
    export class Hightlighted {
      // Use the provide inject directly into the host component
      constructor (@Optional @Host private myService: MyService) {}
    }

    Lesson

  • 相关阅读:
    linux基础命令一
    Mac安装vue cli或者electron时 npm i 报错
    记MacOS抹盘后--使用U盘安装MacOS实录
    腾讯云申请SSL证书与Nginx配置Https
    Windows Server 2016 安装虚拟机版黑群晖
    FreeNas搭建踩坑指南(三)
    FreeNas搭建踩坑指南(二)
    FreeNas搭建踩坑指南(一)
    Apache2配置多域名站点及支持https
    ubuntu server 16.04 开启root密码登录
  • 原文地址:https://www.cnblogs.com/Answer1215/p/8856208.html
Copyright © 2020-2023  润新知