zoukankan      html  css  js  c++  java
  • [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

  • 相关阅读:
    C语言-if语句
    C语言-表达式
    C语言-基础
    Java for LeetCode 187 Repeated DNA Sequences
    Java for LeetCode 179 Largest Number
    Java for LeetCode 174 Dungeon Game
    Java for LeetCode 173 Binary Search Tree Iterator
    Java for LeetCode 172 Factorial Trailing Zeroes
    Java for LeetCode 171 Excel Sheet Column Number
    Java for LeetCode 169 Majority Element
  • 原文地址:https://www.cnblogs.com/Answer1215/p/8856208.html
Copyright © 2011-2022 走看看