Host

首先我们需要先理解一个名词:宿主元素(Host Element)。

什么是宿主元素?

组件或指令为宿主的元素,比如:

<user-detail log></user-detail>

从浏览器角度看,对于指令 log 的宿主是 user-detail DOM元素,而对于组件 user-detail 的宿主就是自身。

有什么用?

那么宿主元素到底有什么用呢?假如 log 指令是为了实现当点击时增加一次计数,那么在使用该指令是这样:

<div log>click</div>

log 指令内部是如何定义 click 事件的呢?

@Directive({
    selector: '[log]',
    host: {
        '(click)': 'onClick()'
    }
})
export class Log {
    onClick() { console.log('click'); }
}

在装饰器里增加 host 对象,而且发现没有,写法就跟绑定语法完全一样,更多写法见绑定语法

这里 host 绑定了一个 click 事件,那么,我们按绑定语法的其它规则,可以直接在 host 加上类名:btn。

@Directive({
    selector: '[log]',
    host: {
        '(click)': 'onClick()',
        '[class]': 'cls'
    }
})
export class Log {
    cls: string = 'btn';

    onClick() { console.log('click'); }
}

注:cls 指的是指令类的属性。

语法糖

我不清楚大家有没有发现一个细节,绑定语法的右边是一个字符串、字符串、字符串,假如更改了 cls 变量名,然后需要再更改 host 中的变量名。

要是不小心忘记了,好累哇,于是……出现了两个语法糖:

  • @HostListener 针对事件处理。
  • @HostBinding 针对于属性绑定。

同样的 log 指令改写成:

@Directive({ selector: '[log]' })
export class Log {

    @HostBinding('class')
    cls: string = 'btn';

    @HostListener('click', [ '$event' ])
    onClick(event: Event) {
        console.log('click', event);
    }
}

爽了!

这里还有一个知识点,是关于样式里也支持 host 概念,而这一点,我统一在样式中描述。

访问宿主DOM元素

Angular提供一个 ElementRef 允许我们直接对原生DOM进行操作,虽然这样子做不科学,但有时候不得不的情况下,还是蛮方便的。

@Directive({ selector: '[log]' })
export class Log {
    constructor(el: ElementRef) {
        console.log(el.nativeElement);
    }
}

它只有一个 nativeElement 属性,正如其名一样。

注:Web Worker 环境无法操作DOM。

results matching ""

    No results matching ""