@Host和@Self在角度上有什么区别?

时间:2018-06-29 02:35:21

标签: angular

在角度docs中,我找到了以下段落:

  

指定注入器仅应从自身获取依赖项。

     

指定注入器应从任何注入器检索依赖项,直到到达当前组件的宿主元素为止。

“主机元素”是什么意思?

1 个答案:

答案 0 :(得分:2)

主机元素:

宿主元素的概念适用于指令和组件。

对于指令,这个概念相当简单。放置指令属性的任何模板标记都被视为宿主元素。

如果我们像这样实现上面的HighlightDirective指令:

<div>
  <p appHighlight>
    <span>Text to be highlighted</span>
  </p>
</div>

<p>标签将被视为宿主元素。如果我们使用自定义TextBoxComponent作为主机,则代码将如下所示:

<div>
  <app-my-text-box appHighlight>
    <span>Text to be highlighted</span>
  </app-my-text-box>
</div>
在组件的上下文中,主机元素是您通过组件配置中的选择器字符串创建的标记。对于上面示例中的TextBoxComponent,组件类上下文中的host元素将是标签。

@Self

@Self装饰器告诉DI仅从自身查找依赖项,这样它就不会在树上行走

Angular只会为该指令/组件所在的元素寻找绑定在组件注入器上的值。

class Dependency {}

@Injectable()
class NeedsDependency {
  constructor(@Self() public dependency: Dependency) {}
}

let inj = ReflectiveInjector.resolveAndCreate([Dependency, NeedsDependency]);
const nd = inj.get(NeedsDependency);

expect(nd.dependency instanceof Dependency).toBe(true);

inj = ReflectiveInjector.resolveAndCreate([Dependency]);
const child = inj.resolveAndCreateChild([NeedsDependency]);
expect(() => child.get(NeedsDependency)).toThrowError();

@Host

@Host装饰器告诉DI在任何注入器中寻找依赖项,直到到达宿主为止

Angular将寻找一个值,该值绑定到该指令/组件所在的元素的组件注入器或父组件的注入器上。 Angular将此父组件称为“主机”。

class OtherService {}
class HostService {}

@Directive({selector: 'child-directive'})
class ChildDirective {
  logs: string[] = [];

  constructor(@Optional() @Host() os: OtherService, @Optional() @Host() hs: HostService) {
    // os is null: true
    this.logs.push(`os is null: ${os === null}`);
    // hs is an instance of HostService: true
    this.logs.push(`hs is an instance of HostService: ${hs instanceof HostService}`);
  }
}

@Component({
  selector: 'parent-cmp',
  viewProviders: [HostService],
  template: '<child-directive></child-directive>',
})
class ParentCmp {
}

@Component({
  selector: 'app',
  viewProviders: [OtherService],
  template: '<parent-cmp></parent-cmp>',
})
class App {
}

收听元素主机:

监听主机(即,指令附加到的DOM元素)是指令扩展组件或元素行为的主要方式之一。以前,我们看到了它的常见用例。

@Directive({
  selector: '[appMyDirective]'
})
class MyDirective {
  @HostListener('click', ['$event'])
  onClick() {}
}

我们还可以通过在侦听器中添加目标来响应外部事件,例如来自窗口或文档的外部事件。

@Directive({
  selector: `[appHighlight]`
})
export class HighlightDirective {
  constructor(private el: ElementRef, private renderer: Renderer) { }

  @HostListener('document:click', ['$event'])
  handleClick(event: Event) {
    if (this.el.nativeElement.contains(event.target)) {
      this.highlight('yellow');
    } else {
      this.highlight(null);
    }
  }

  highlight(color) {
    this.renderer.setElementStyle(this.el.nativeElement, 'backgroundColor', color);
  }
}

示例:https://plnkr.co/edit/iJvMpPYDQmiwqvUTKSU8?p=preview